Как мне защитить свою кодовую базу Python, чтобы гости не могли видеть определенные модули, но чтобы она продолжала работать?

StackOverflow https://stackoverflow.com/questions/1443146

Вопрос

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

Допустим, в нашем проекте Foo есть модуль, bar, с одной функцией, get_sauce().Что на самом деле происходит в get_sauce() секретно, но мы хотим общедоступную версию get_sauce() чтобы вернуть приемлемый, хотя и неверный результат.

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

Симлинки

Моей первой мыслью было создание символических ссылок. Вместо bar.py, предоставлять bar_public.py всем и bar_private.py только внутренним разработчикам.К сожалению, создание символических ссылок — это утомительная ручная работа, особенно когда таких частных модулей действительно будет около двух десятков.

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

Несколько репозиториев

Следующей мыслью было иметь два репозитория:

private
└── trunk/
    ├── __init__.py
    └── foo/
        ├── __init__.py
        └── bar.py
public
└── trunk/
    ├── __init__.py
    └── foo/
        ├── __init__.py
        ├── bar.py
        ├── baz.py
        └── quux.py

Идея состоит в том, что только внутренние разработчики смогут проверить оба варианта. private/ и public/.Внутренние разработчики установят свои PYTHONPATH=private/trunk:public/trunk, но все остальные просто установят PYTHONPATH=public/trunk.Тогда как инсайдеры, так и посторонние смогут from foo import bar и получить правильный модуль, верно?

Давайте попробуем это:

% PYTHONPATH=private/trunk:public/trunk python
Python 2.5.1
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo.bar
>>> foo.bar.sauce()
'a private bar'
>>> import foo.quux
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named quux

Я не эксперт по Python, но кажется, что Python уже принял решение по поводу модуля. foo и поиск относительно этого:

>>> foo
<module 'foo' from '/path/to/private/trunk/foo/__init__.py'>

Даже не удаляя foo помогает:

>>> import sys
>>> del foo
>>> del sys.modules['foo']
>>> import foo.quux
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named quux

Можете ли вы предоставить мне лучшее решение или предложение?

Это было полезно?

Решение

в __init__ метод foo пакет, который вы можете изменить __path__ чтобы заставить его искать свои модули в других каталогах.

Итак, создайте каталог с именем secret и поместите его в свой личный репозиторий Subversion.В secret поместите свой собственный bar.py__init__.py общественности foo пакет поместил что-то вроде:

__path__.insert(0,'secret')

Это будет означать для пользователей, у которых есть частный репозиторий и поэтому secret каталог, который они получат в собственность bar.py как foo.bar как secret — это первый каталог в пути поиска.Для других пользователей Python не найдет secret и будет выглядеть как следующий каталог в __path__ и так загрузится нормально bar.py от foo.

Итак, это будет выглядеть примерно так:

   private
    └── trunk/
        └── secret/
            └── bar.py
    public
    └── trunk/
        ├── __init__.py
        └── foo/
            ├── __init__.py
            ├── bar.py
            ├── baz.py
            └── quux.py

Другие советы

Используйте какую-то систему плагинов и храните свои плагины при себе, но также имейте общедоступные плагины, которые поставляются с открытым кодом.

Систем плагинов предостаточно.Вы можете легко сделать очень простые сами.Если вам нужно что-то более продвинутое, я предпочитаю архитектуру компонентов Zope, но есть также такие варианты, как setuptools enter_points и т. д.

Какой из них использовать в вашем случае, будет хорошим вторым вопросом.

Вот альтернативное решение, которое я заметил при чтении документации для Колба:

flaskext/__init__.py

Единственная цель этого файла — пометить пакет как пакет пространства имен.Это необходимо для того, чтобы несколько модулей из разных пакетов PyPI могли находиться в одном пакете Python:

__import__('pkg_resources').declare_namespace(__name__)

Если вы хотите точно знать, что там происходит, ознакомьтесь с документацией по дистрибутиву или setuptools, в которой объясняется, как это работает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top