Como posso proteger o meu Python codebase para que os hóspedes não podem ver alguns módulos, mas por isso ainda funciona?

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

Pergunta

Estamos começando um novo projeto em Python com alguns algoritmos proprietários e pedaços sensíveis da lógica que nós gostaríamos de manter privadas. Teremos também algumas pessoas de fora (selecionar os membros do público) que trabalham no código. Não podemos conceder o acesso de pessoas de fora para os pequenos pedaços, privados de código, mas gostaria de uma versão pública para o trabalho bem o suficiente para eles.

dizer que o nosso projecto, Foo, tem um módulo, bar, com uma função, get_sauce(). O que realmente acontece em get_sauce() é secreto, mas queremos uma versão pública do get_sauce() para retornar um aceitável, embora incorreto, resultado.

Nós também executar o nosso próprio servidor Subversion por isso temos o controle total sobre quem pode acessar o quê.

Symlinks

O meu primeiro pensamento foi criar um link simbólico - Em vez de bar.py, fornecer bar_public.py a todos e bar_private.py apenas para desenvolvedores internos. Infelizmente, a criação de links simbólicos é, trabalho manual tedioso -. Especialmente quando há realmente vai ser cerca de duas dezenas desses módulos privadas

Mais importante, ele faz o gerenciamento do arquivo authz Subversion difícil, uma vez que para cada módulo queremos proteger uma exceção deve ser adicionado no servidor. Alguém pode esquecer de fazer isso e, acidentalmente, o check-in segredos ... Em seguida, o módulo está no repo e temos que reconstruir o repositório sem ele e esperança de que um estranho não baixá-lo nesse meio tempo.

vários repositórios

O próximo pensamento era ter dois repositórios:

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

A idéia é que apenas os desenvolvedores internos será capaz de fazer o checkout tanto private/ e public/. desenvolvedores internos irá definir sua PYTHONPATH=private/trunk:public/trunk, mas todo mundo vai apenas definir PYTHONPATH=public/trunk. Em seguida, ambos os insiders e outsiders pode from foo import bar e obter o módulo certo, certo?

Vamos tentar isso:

% 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

Eu não sou um especialista em Python, mas parece que Python já fez a sua mente sobre o módulo foo e pesquisas relativas a esse:

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

Nem mesmo apagar foo ajuda:

>>> 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

Você pode me fornecer uma solução melhor ou sugestão?

Foi útil?

Solução

No método __init__ do foo pacote que você pode mudar __path__ para torná-la para seus módulos em outros diretórios.

Portanto, criar um diretório chamado secret e colocá-lo em seu repositório Subversion privado. Em secret colocar o seu bar.py proprietário. No __init__.py do pacote foo público colocar em algo como:

__path__.insert(0,'secret')

Isto significa para os usuários que têm o repositório privado e assim o diretório secret que irão receber o bar.py proprietário como foo.bar como secret é o primeiro diretório no caminho de pesquisa. Para outros usuários, Python não vai encontrar secret e vai olhar como o próximo diretório no __path__ e assim vai carregar o bar.py normal a partir foo.

Por isso, será algo parecido com isto:

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

Outras dicas

Use algum tipo de sistema de plugins, e manter seus plugins para o seu auto, mas também tem plugins publicamente disponíveis que fica enviados com o código aberto.

sistemas Plugin abundam. Você pode facilmente fazer mais simples morto mesmo. Se você quiser algo mais avançado eu prefiro a arquitetura Zope componente, mas também há opções como Setuptools entry_points, etc.

Qual deles usar no seu caso seria uma boa segunda pergunta.

Aqui está uma solução alternativa que eu notei ao ler a documentação para Flask :

flaskext/__init__.py

A única finalidade deste arquivo é para marcar o pacote como pacote namespace. Isso é necessário para que vários módulos de diferentes pacotes PyPI pode residir no mesmo pacote Python:

__import__('pkg_resources').declare_namespace(__name__)

Se você quer saber exatamente o que está acontecendo lá, verificação geral a distribuir ou setuptools docs que explicar como isso funciona.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top