понедельник, 8 августа 2016 г.

Польза архитектуры для создания безопасных продуктов



Завтра (9 августа 2016) выступаю в Летней школе CTF с лекцией о пользе архитектурных артефактов для создания безопасных решений. Пока выяснял как туда лучше доехать выяснил интересный факт из жизни Подмосковья:
  • Маршрут Зеленоград — Университет Дубна: около 140 км на автомобиле и примерно 5 часов на общественном транспорте.
  • Маршрут Зеленоград — Мариинский театр: около 680 км на автомобиле и примерно 5 часов на общественном транспорте.
Отсюда выводы: во-первых, Питер стал невероятно близок к Москве после появления скоростных поездов, и это невероятно круто. Во-вторых, подмосковные центры научного притяжения до сих пор остаются сложнодоступными и это очень печально.

Видео доклада:

понедельник, 1 августа 2016 г.

Создаем и публикуем модуль Python



В прошлый раз я описал шаги по освоению Питона для разработчика С++. Теперь, разобравшись с основами, можно начинать создавать свои первые проекты. Как и в других языках для этой цели разработчики используют какой-либо фреймворк, который зачастую определяет структуру программы, но этот путь может быть опишу в другой раз. Сегодня посмотрим на структуру типичного пакета Python.

Разницы с C++ тут большой нет — программой может быть как один файл, так и группа файлов. Упрощенно можно сказать, что один файл — это модуль (module), а набор модулей в пределах одной директории — пакет (package) или библиотека. Пакет также может содержать в себе дочерние пакеты. Поскольку язык интерпретируемый, то запускать на выполнение отдельные файлы можно следующим образом:
$ python foo.py
Если у вас в системе установлен какой-либо пакет, либо вы просто находитесь в директории, где есть пакет, то запустить его можно так:
$ python -m bar.foo
Где foo — это файл foo.py в пакете bar. У пакетов есть также скрипты с зарезервированными названиями, которые запускаются автоматически. Так, если в пакете bar есть скрипт __main__.py, то он будет запущен автоматически при выполнении python -m bar.

Также стоит обратить внимание на файл __init__.py. Именно его наличие говорит Питону, что данная директория является пакетом. Часто бывает, что этот файл оставляют пустым, но можно там разместить какие-то общие для всех модулей вещи.

Теперь посмотрим на небольшой пакет из реальной жизни и его структуру. Для пояснений я буду использовать свой проект ZXTools, который предназначен для работы со старыми дисками от ZX-Spectrum. Как-нибудь я подробнее расскажу о процессе разбора дискет от Спектрума. Пока же посмотрим на структуру проекта. Он состоит из двух директорий (test и zxtools) и из нескольких файлов в корне. Далее рассмотрим зачем там каждый из них.

LICENSE

Файл LICENSE очень важен для публикации вашей работы и это касается не только Python. Текст лицензии позволяет другим понять можно ли использовать результаты вашего труда и если да, то как именно. GitHub при создании нового проекта предлагает создать этот файл включив туда одну из стандартных лицензий.

README.rst

Файл README также должен быть хорошо знаком тем, кто уже публиковал свои работы или использовал чужие. Тут указывается полезная информация о проекте, для чего он предназначен и как им пользоваться. Обратите внимание на формат файла. Чаще встречаются файлы README.md, что означает файл в формате Markdown, но для проектов на Python лучше использовать reStructuredText, так как только его корректно поддерживает Python Package Index. А ведь именно на PyPI публикуются пакеты, которые потом легко устанавливаются с помощью пакета pip. GitHub прекрасно поддерживает RST формат, поэтому вы ничего не потеряете.

Makefile

«Что в проекте на Python делает Makefile?» — спросите вы. А делает он то же, что и в C++ — автоматизирует некоторые шаги. В моем проекте он используется для удобной очистки директории (знакомая цель clean), для запуска юнит-тестов (цель test), для анализа тестового покрытия (цель coverage) и для статического анализа (цель lint). Если вы ведете разработку под Windows, то Makefile возможно окажется не самым привычным средством. Тогда используйте привычный и удобный именно вам механизм, но не слишком усложняйте.

setup.py

Файл setup.py нужен для автоматизации публикации и установки вашего пакета. По сути, это очередной файл на Питоне, в котором вы вызываете функцию setup пакета setuptools. В функцию setup вы передаете параметры, которые описывают ваш пакет: имя пакета, номер версии, тип лицензии, описание, имя автора, ссылки на документацию и исходные файлы, список дочерних пакетов, список зависимостей, классификаторы. В примере есть все, что вы захотите использовать вначале. Но подробнее про все параметры можно посмотреть в документации.

Полезно тут же указать какие командные скрипты необходимо создать при установке. Такие скрипты сильно упрощают использование вашего пакета, так как не нужно будет помнить в каком пакете находятся нужные команды и не нужно писать длинную строку их вызова. В примере можно видеть раздел entry_points, в котором определены две команды:
entry_points={
        'console_scripts': [
            'zeus2txt = zxtools.zeus2txt:main',
            'hobeta = zxtools.hobeta:main',
        ],
    },
Команды имеют следующий формат: <имя пакета>.<имя модуля>:<имя функции>.

Также стоит обратить внимание на параметр test_suite. В нем указывается пакет, который отвечает за тестирование вашего проекта. В данном случае указан пакет test.

Публикация, запуск тестов и continuous integration

Я уже упоминал, что самое популярное место для публикации пакетов — это индекс PyPI. Помимо этого, для открытых проектов TravisCI предоставляет бесплатную возможность запуска тестов на каждый коммит, а codecov.io позволяет отслеживать изменение покрытия и сигнализирует о проблемах. Именно эти средства я использовал в ZXTools. В следующий раз подробнее расскажу как опубликовать пакет, автоматически запускать проверку тестов, считать покрытие и как добавить красивые бейджики с информацией об этих процессах.

Книги по теме:

  1. Марк Лутц. Программирование на Python. Том 1
  2. Марк Лутц. Программирование на Python. Том 2

понедельник, 6 июня 2016 г.

 Мой путь из C++ в Python

Этот текст кратко поясняет как мне удалось быстро начать писать программы на Python. Все, что описывается, основывается на личном опыте и ощущениях, и поэтому может не описывать тот самый единственно верный путь. Тем не менее, изложенная информация агрегирует знания, которые пришлось собрать, чтобы создавать собственные проекты на Python. Для начала не огромные высокопроизводительные системы, но и на C++ вы тоже не сразу стали выдавать шедевры. Если у кто-то посчитает, что тут не хватает важных вещей, о который обязательно нужно сказать, то в комментариях можно это отметить.

Начинать разработку конечно нужно с установки интерпретатора. Повезло тем, у кого установлена операционная система семейства Linux — тогда вопрос установки скорее всего не стоит и интерпретатор Python уже установлен. Если Python не установлен, то инсталлятор для всех популярных ОС совершенно бесплатно можно скачать с официального сайта.

После этого можно попробовать запустить Python, но никакой среды разработки вы не увидите, а увидите интерактивную консоль:

Из интересного на картинке — версия языка. Очень много кода и библиотек существует для версии 2.7 и поэтому повсеместный переход на ветку 3.5 слегка затянулся. Но все-таки я рекомендую изучать именно 3.5. При необходимости вы сможете писать и для 2.7, при этом будете знать более современную редакцию.

Хотя этот вопрос и не такой популярный как про выход из Vim, но сразу подскажу, что выйти из интерактивного режима можно написав quit().

Если очень хочется какую-нибудь среду разработки, то PyCharm мне показалось наиболее удобной (помимо платной версии есть и Community Edition). Под Windows конечно еще есть привычная Visual Studio с Python Tools.

С инструментами покончено, время понять какие важные отличия от C++ нужно сразу усвоить. Во-первых, Python использует duck typing. Это означает, что если в какой-то момент выполнения программы объект имеет все свойства класса, то он в этот момент считается объектом этого класса. Если сравнивать с C++, то ближе всего к этому концепты (Concepts), которые кстати не попадут в C++17.

If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck.

Во-вторых, многопоточности в Python нет. Если вы будете мучить Google на эту тему, то скорее всего наткнетесь на GIL (Global Interpreter Lock), но это совсем не та многопоточность, к которой привыкли C++ разработчики. Схематично принцип такой многопоточности показан на картинке — тут хорошо видно, что параллельно никакие потоки не выполняются, даже если у вас многоядерный процессор:

GIL description

Полноценная многопоточность обычно реализуется за счет запуска отдельных процессов. Для начала это все, что нужно знать про многопоточность в Python.

Остальные вопросы, которые часто возникают у новичков, и ответы на них можно найти на StackOverflow.com в секции с часто задаваемыми вопросами. Стоит просмотреть первых штук 50.

Из этих вопросов вы узнаете, что файлы на Python имеют расширение py и их стоит начинать со следующей строки:

#! /usr/bin/env python
Это позволяет запускать скрипт в виртуальных окружениях с разными версиями Python. Сам же Python выполняет файл последовательно с первой строки и далее. При этом нет никакой функции main, как в C или C++. Хотя часто в скриптах встречается строка if __name__ == "__main__", которую ошибочно можно принять за точку входа. Но нет, если за пределами этого выражения будет другой код, то он также выполнится. А само выражение удобно использовать для создания и запуска тестов в подключаемых модулях.

В следующий раз расскажу как создать модуль и тесты для него, и как это потом опубликовать и «непрерывно интегрировать». А ниже моя первая программа на Python:

#! /usr/bin/env python
# vim: set fileencoding=utf-8 :
""" Hello world in Python """

def main():
    print("Hello world!")

if __name__ == "__main__":
    main()

Книги по теме:

  1. Марк Лутц. Программирование на Python. Том 1
  2. Марк Лутц. Программирование на Python. Том 2

вторник, 17 мая 2016 г.

hex dump


Постоянные пользователи Vim наверняка слышали об утилите xxd. Она позволяет вывести дамп указанного файла. Выглядит это следующим образом:
$ xxd -l 64 db.sqlite3 
0000000: 5351 4c69 7465 2066 6f72 6d61 7420 3300  SQLite format 3.
0000010: 0400 0101 0040 2020 0000 0013 0000 0024  .....@  .......$
0000020: 0000 0000 0000 0000 0000 0017 0000 0004  ................
0000030: 0000 0000 0000 0000 0000 0001 0000 0000  ................
Параметр -l 64 указывает, что нужно вывести только первые 64 байта. Есть еще один любопытный параметр (-i), который позволяет сгенерировать код, и его можно сразу вставлять в C или C++ файл:
$ xxd -i -l 64 db.sqlite3
unsigned char db_sqlite3[] = {
  0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61,
  0x74, 0x20, 0x33, 0x00, 0x04, 0x00, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20,
  0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00
};
unsigned int db_sqlite3_len = 64;
Параметров для генерации кода для других языков не предусмотрено. Но это поправимо. Например, мне понадобилось вставить код в модульные тесты на Python 3. Помог в этом потоковый редактор sed:
$ xxd -l 64 -g 1 -u db.sqlite3 | sed -e 's/.\+: /b"\\x/g' -e 's/  .*/"/g' -e 's/ /\\x/g'
b"\x53\x51\x4C\x69\x74\x65\x20\x66\x6F\x72\x6D\x61\x74\x20\x33\x00"
b"\x04\x00\x01\x01\x00\x40\x20\x20\x00\x00\x00\x13\x00\x00\x00\x24"
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x04"
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
И кстати, вскоре я поделюсь опытом как быстро начать писать программы на Python.


Книги по теме:
  1. Дню Нейл. Практическое использование Vim
  2. Марк Лутц. Программирование на Python. Том 1

вторник, 5 апреля 2016 г.

В Visual Studio добавилась поддержка сборки под Linux



Итак, в Visual Studio теперь можно компилировать и отлаживать проекты под Linux. Можно было бы подумать, что это первоапрельская шутка, но нет — новость была выложена 30 марта. Кроме того, я уже попробовал — это реально работает.

Visual Studio использует доступ по ssh на удаленную машину с Linux. Туда автоматически копируются необходимые исходные файлы, которые потом там же и компилируются. При необходимости запускается gdbserver для организации удаленной отладки. Все это делается незаметно и не требует ручной настройки. Надо учитывать, что это самая первая версия и для продакшена пока не годится.

На первый взгляд видятся следующие недостатки:
  1. Копирование файлов на удаленную машину не выглядит безопасным. Канал конечно защищен, но вот сама удаленная машина может контролироваться потенциальным нарушителем.
  2. Копирование большого проекта может занять продолжительное время.
  3. На удаленной машине элементарно может не быть места для всех сорсов и объектных файлов.

Также пока не реализовано отображение стандартного вывода в Output в самой Visual Studio. То есть, программа удаленно работает и что-то пишет в консоль, но прочитать это нельзя. Но этот недостаток скоро исправят, так как он уже есть в бэклоге команды разработки.

Подробнее: https://blogs.msdn.microsoft.com/vcblog/2016/03/30/visual-c-for-linux-development/

воскресенье, 3 апреля 2016 г.

Сценарии как развитие идеи сторимаппинга



Директор небольшой брокерской фирмы Юрий сидел в офисе, который он арендовал в модном коворкинге вместе со своими немногочисленными сотрудниками. Компания последнее время показывала очень хорошие результаты. Престижное экономическое образование позволило самостоятельно построить успешную компанию, а вот как обезопасить основной капитал – базу клиентов – от участившихся хакерских атак собственными силами Юрий не знал. Своим сотрудникам Юрий доверял, но они часто работали из дома, из кафе, да и местный администратор Илья не вызывал доверия, наверное из-за бороды и черной футболки.

Такие мысли уже давно сопровождали Юрия и новый билборд, который недавно повесили как раз напротив окон офиса, дал импульс к конкретным шагам. На билборде компания PrivateNet обещала защитить важные данные и коммуникации в компании.

Секретарь Юля не только носила кофе боссу, но и выполняла самые ответственные поручения. Поэтому письмо Юрия о необходимости приобрести решение некой PrivateNet не вызвали удивления. Юля быстро нашла в интернете сайт компании и уверенно выбрала пакет для компании от 2 до 25 человек и оплатила пластиковой картой. Ввела адреса всех сотрудников (да, они все на mail.ru, но сервис вроде надежный и корпоративная почта получается бесплатно), телефоны, количество лицензий на каждый адрес и ввела сопроводительный текст от своего имени, чтобы письмо с ссылкой не попало в спам. Нажать кнопку «Уведомить сотрудников» и дело сделано. Ах да, проверить что все сработало. Юля проверила почту на своем MacBook Air и на iPhone. Все установилось без проблем, а в личном кабинете на портале PrivateNet красовалась зеленая цифра 2. Отлично, как будет 11, то можно будет сообщить Юре, что мы в безопасности.
<...>

Что дает аналитику эта мини-история? Зачем вообще аналитик станет писать подобный текст? Ведь можно было обойтись обычным списком — на какой сегмент рынка рассчитан продукт, какие проблемы пользователя решает, кто принимает решение о покупке, кто является пользователем продукта, какой канал распространения, какие платформы поддерживаются, роли пользователей продукта, кому доверяем, а кто может быть нарушителем и многое другое.

Но, во-первых, связная история легко запоминается, а во-вторых, содержит много неявных деталей. Например, разработчики вряд ли будут рассчитывать, что Юля, являясь по сути администратором организации, станет править конфиги. Или кто-то думает, что Юля знает какие ОС на устройствах сотрудников? Серьезно?

А еще из сценария мы узнаем о сомнительном типе — Илье, который имеет непосредственный доступ к сетевому оборудованию, а также о наличии других пользователей-потенциальных-нарушителей в той же физической сети коворкинга. Не забываем о том, что сотрудники не всегда работают из офиса. Кажется, уже достаточно данных, чтобы начинать строить модель нарушителя.

Также сценарий позволяет оценить целостность требований — не упустили ли чего-то важного или, наоборот, сделали слишком далеко идущие предположения. Например, в данном примере сразу видно, что не раскрыт важный аспект продукта — что он собственно делает и как именно решает проблему пользователя. А еще кого-то из проектной команды может подвергнуть сомнению безусловное доверие к провайдеру корпоративной почты.

И это еще не все. В отделе продаж всем будет понятно что именно они продают, и как лучше организовать продажи. Что стоит написать на билбордах, или билбордов вообще не будет? А что будет вместо них? Как лучше подтолкнуть Юрия к решению о покупке? Все коррективы сразу вносим в сценарий и проверяем как все складывается в непрерывную историю.

Другими словами, сценарии позволяют упорядочить хаос и служат инструментом верификации вижена продукта внутри команды. К тому же, читать их много интересней, чем сухие требования. А как вы это делаете?

Названия компаний и имена людей выдуманы, все совпадения случайны.

Книги по теме:

понедельник, 28 марта 2016 г.

Использование UTF-8 в исходных кодах


Некоторые время назад возникла задача проверить совместимость компиляторов с исходными файлами в представлении UTF-8 с маркером и без него. Маркер BOM был придуман для индикации порядка байт в машинных словах. Несмотря на то, что UTF-8 — это байтовый поток и такой маркер не имеет большого смысла в его первоначальном понимании, многие утилиты корректно работают только при наличии маркера в файле. Для обозначения UTF-8 в начало файла вставляется последовательность EF16, BB16, BF16. Файлы в кодировке UTF-8 без маркера неотличимы от ASCII файлов, если используются только 7-битные символы.

В результате эксперимента исследовались файлы в вариантах Unicode (UTF-8 with signature) – Codepage 65001 и Unicode (UTF-8 without signature) – Codepage 65001 для Visual Studio 2013, Visual Studio 2008 и Visual Studio 2014 CTP2. Для полноты сравнения в системе Linux была проведена аналогичная проверка с компилятором GNU C++ 4.7.2. В качестве редактора в Linux использовался vi с опциями set [no]bomb для получения файлов с маркером и без него.