mirror of
https://github.com/cmehay/docker-tor-hidden-service.git
synced 2025-04-21 14:29:11 +00:00
Add pre-commit
This commit is contained in:
parent
27dd14ab33
commit
f206ea354c
8 changed files with 114 additions and 40 deletions
21
.pre-commit-config.yaml
Normal file
21
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
- repo: git://github.com/pre-commit/pre-commit-hooks
|
||||||
|
sha: v0.9.1
|
||||||
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: check-docstring-first
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: flake8
|
||||||
|
args:
|
||||||
|
- --exclude=__init__.py
|
||||||
|
language_version: python3
|
||||||
|
- id: autopep8-wrapper
|
||||||
|
language_version: python3
|
||||||
|
- id: requirements-txt-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- repo: git://github.com/asottile/reorder_python_imports
|
||||||
|
sha: v0.3.5
|
||||||
|
hooks:
|
||||||
|
- id: reorder-python-imports
|
||||||
|
language_version: python3
|
|
@ -4,5 +4,7 @@ python:
|
||||||
- "3.4"
|
- "3.4"
|
||||||
- "3.5"
|
- "3.5"
|
||||||
- "3.6"
|
- "3.6"
|
||||||
install: pip install tox-travis
|
install: pip install tox-travis pre-commit
|
||||||
script: tox
|
script:
|
||||||
|
- pre-commit run --all-files
|
||||||
|
- tox
|
||||||
|
|
28
README.md
28
README.md
|
@ -90,6 +90,34 @@ To increase security, it's possible to setup your service through socket between
|
||||||
|
|
||||||
__Warning__: Due to a bug in `tor` configuration parser, it's not possible to mix network link and socket link in the same `tor` configuration.
|
__Warning__: Due to a bug in `tor` configuration parser, it's not possible to mix network link and socket link in the same `tor` configuration.
|
||||||
|
|
||||||
|
### Group services
|
||||||
|
|
||||||
|
Multiple services can be hosted behind the same onion address.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
links:
|
||||||
|
- hello
|
||||||
|
- world
|
||||||
|
- hey
|
||||||
|
environment:
|
||||||
|
# Set mapping ports
|
||||||
|
HELLO_PORTS: 80:80
|
||||||
|
|
||||||
|
# Multiple ports can be coma separated
|
||||||
|
WORLD_PORTS: 8000:80,8888:80,22:22
|
||||||
|
|
||||||
|
# Socket mapping is supported
|
||||||
|
HEY_PORTS: 80:unix:/var/run/socket.sock
|
||||||
|
|
||||||
|
# hello and world will share the same onion address
|
||||||
|
# Service name can be any string as long there is not special char
|
||||||
|
HELLO_SERVICE_NAME: foo
|
||||||
|
WORLD_SERVICE_NAME: foo
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
__Warning__: Be carefull to not use the same exposed ports for grouped services.
|
||||||
|
|
||||||
### Compose v2 support
|
### Compose v2 support
|
||||||
|
|
||||||
Links setting are required when using docker-compose v2. See `docker-compose.v2.yml` for example.
|
Links setting are required when using docker-compose v2. See `docker-compose.v2.yml` for example.
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os
|
|
||||||
from json import dumps
|
|
||||||
|
|
||||||
from re import match
|
|
||||||
|
|
||||||
from pyentrypoint import DockerLinks
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from json import dumps
|
||||||
|
from re import match
|
||||||
|
|
||||||
from jinja2 import Environment
|
from jinja2 import Environment
|
||||||
from jinja2 import FileSystemLoader
|
from jinja2 import FileSystemLoader
|
||||||
|
from pyentrypoint import DockerLinks
|
||||||
|
|
||||||
from .Service import ServicesGroup, Service
|
from .Service import Service
|
||||||
|
from .Service import ServicesGroup
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
class Setup(object):
|
class Setup(object):
|
||||||
|
@ -163,13 +160,10 @@ class Setup(object):
|
||||||
|
|
||||||
def setup_hosts(self):
|
def setup_hosts(self):
|
||||||
self.setup = {}
|
self.setup = {}
|
||||||
try:
|
self._get_setup_from_env()
|
||||||
self._get_setup_from_env()
|
self._get_setup_from_links()
|
||||||
self._get_setup_from_links()
|
self.check_services()
|
||||||
self.check_services()
|
self.apply_conf()
|
||||||
self.apply_conf()
|
|
||||||
except BaseException:
|
|
||||||
raise Exception('Something wrongs with setup')
|
|
||||||
|
|
||||||
def check_services(self):
|
def check_services(self):
|
||||||
for group in self.services:
|
for group in self.services:
|
||||||
|
@ -263,15 +257,26 @@ def main():
|
||||||
help='Setup hosts')
|
help='Setup hosts')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
onions = Onions()
|
try:
|
||||||
if args.setup:
|
onions = Onions()
|
||||||
onions.setup_hosts()
|
if args.setup:
|
||||||
return
|
onions.setup_hosts()
|
||||||
onions.torrc_parser()
|
else:
|
||||||
|
onions.torrc_parser()
|
||||||
|
except BaseException as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
else:
|
||||||
|
error_msg = None
|
||||||
if args.json:
|
if args.json:
|
||||||
|
if error_msg:
|
||||||
|
print(dumps({'error': error_msg}))
|
||||||
|
sys.exit(1)
|
||||||
logging.getLogger().setLevel(logging.ERROR)
|
logging.getLogger().setLevel(logging.ERROR)
|
||||||
print(onions.to_json())
|
print(onions.to_json())
|
||||||
else:
|
else:
|
||||||
|
if error_msg:
|
||||||
|
logging.error(error_msg)
|
||||||
|
sys.exit(1)
|
||||||
print(onions)
|
print(onions)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
'This class define a service link'
|
'This class define a service link'
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from base64 import b32encode
|
||||||
|
from hashlib import sha1
|
||||||
|
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from hashlib import sha1
|
|
||||||
from base64 import b32encode
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
class ServicesGroup(object):
|
class ServicesGroup(object):
|
||||||
|
@ -18,6 +17,9 @@ class ServicesGroup(object):
|
||||||
hidden_service_dir = "/var/lib/tor/hidden_service/"
|
hidden_service_dir = "/var/lib/tor/hidden_service/"
|
||||||
|
|
||||||
def __init__(self, name=None, service=None, hidden_service_dir=None):
|
def __init__(self, name=None, service=None, hidden_service_dir=None):
|
||||||
|
|
||||||
|
name_regex = r'^[a-zA-Z0-9-_]+$'
|
||||||
|
|
||||||
self.hidden_service_dir = hidden_service_dir or self.hidden_service_dir
|
self.hidden_service_dir = hidden_service_dir or self.hidden_service_dir
|
||||||
if not name and not service:
|
if not name and not service:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
|
@ -25,6 +27,10 @@ class ServicesGroup(object):
|
||||||
)
|
)
|
||||||
self.services = []
|
self.services = []
|
||||||
self.name = name or service.host
|
self.name = name or service.host
|
||||||
|
if not re.match(name_regex, self.name):
|
||||||
|
raise Exception(
|
||||||
|
'Group {name} has invalid name'.format(name=self.name)
|
||||||
|
)
|
||||||
if service:
|
if service:
|
||||||
self.add_service(service)
|
self.add_service(service)
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
from .Onions import Onions, main
|
from .Onions import main
|
||||||
from .Service import ServicesGroup, Service, Ports
|
from .Onions import Onions
|
||||||
|
from .Service import Ports
|
||||||
|
from .Service import Service
|
||||||
|
from .Service import ServicesGroup
|
||||||
|
|
|
@ -33,7 +33,7 @@ setup(
|
||||||
|
|
||||||
install_requires=['pyentrypoint==0.5.0',
|
install_requires=['pyentrypoint==0.5.0',
|
||||||
'Jinja2>=2.8',
|
'Jinja2>=2.8',
|
||||||
'pycrypto',],
|
'pycrypto', ],
|
||||||
|
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
from onions import Onions
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import pytest
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from Crypto.PublicKey import RSA
|
|
||||||
from hashlib import sha1
|
|
||||||
from base64 import b32encode
|
from base64 import b32encode
|
||||||
|
from hashlib import sha1
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from onions import Onions
|
||||||
|
|
||||||
|
|
||||||
def get_key_and_onion():
|
def get_key_and_onion():
|
||||||
key = '''
|
key = '''
|
||||||
|
@ -40,6 +40,7 @@ bhJ3M9WzP/EMkAzyW8mVs1moFp3hRcfQlZHl6g1U9D8=
|
||||||
|
|
||||||
return key.strip(), onion
|
return key.strip(), onion
|
||||||
|
|
||||||
|
|
||||||
def get_torrc_template():
|
def get_torrc_template():
|
||||||
return r'''
|
return r'''
|
||||||
{% for service_group in services %}
|
{% for service_group in services %}
|
||||||
|
@ -65,6 +66,7 @@ SocksPort 0
|
||||||
# useless line for Jinja bug
|
# useless line for Jinja bug
|
||||||
'''.strip()
|
'''.strip()
|
||||||
|
|
||||||
|
|
||||||
def test_ports(monkeypatch):
|
def test_ports(monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_PORTS': '80:80',
|
'SERVICE1_PORTS': '80:80',
|
||||||
|
@ -104,6 +106,7 @@ def test_ports(monkeypatch):
|
||||||
|
|
||||||
assert check == 10
|
assert check == 10
|
||||||
|
|
||||||
|
|
||||||
def test_docker_links(fs, monkeypatch):
|
def test_docker_links(fs, monkeypatch):
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
|
@ -186,6 +189,7 @@ def test_key(monkeypatch):
|
||||||
|
|
||||||
assert onion.services[0].onion_url == onion_url
|
assert onion.services[0].onion_url == onion_url
|
||||||
|
|
||||||
|
|
||||||
def test_key_in_secret(fs, monkeypatch):
|
def test_key_in_secret(fs, monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_SERVICE_NAME': 'group1',
|
'SERVICE1_SERVICE_NAME': 'group1',
|
||||||
|
@ -284,6 +288,7 @@ def test_configuration(fs, monkeypatch):
|
||||||
(port.port_from, port.dest) for port in service.ports
|
(port.port_from, port.dest) for port in service.ports
|
||||||
) == set([(80, 'unix://unix.socket')])
|
) == set([(80, 'unix://unix.socket')])
|
||||||
|
|
||||||
|
|
||||||
def test_groups(monkeypatch):
|
def test_groups(monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_SERVICE_NAME': 'group1',
|
'SERVICE1_SERVICE_NAME': 'group1',
|
||||||
|
@ -323,6 +328,7 @@ def test_groups(monkeypatch):
|
||||||
|
|
||||||
assert re.match(onion_match, group.onion_url)
|
assert re.match(onion_match, group.onion_url)
|
||||||
|
|
||||||
|
|
||||||
def test_json(monkeypatch):
|
def test_json(monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_SERVICE_NAME': 'group1',
|
'SERVICE1_SERVICE_NAME': 'group1',
|
||||||
|
@ -345,6 +351,7 @@ def test_json(monkeypatch):
|
||||||
assert len(jsn['group1']) == 3
|
assert len(jsn['group1']) == 3
|
||||||
assert len(jsn['group2']) == 1
|
assert len(jsn['group2']) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_output(monkeypatch):
|
def test_output(monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_SERVICE_NAME': 'group1',
|
'SERVICE1_SERVICE_NAME': 'group1',
|
||||||
|
@ -363,6 +370,7 @@ def test_output(monkeypatch):
|
||||||
for item in ['group1', 'group2', '.onion', ',']:
|
for item in ['group1', 'group2', '.onion', ',']:
|
||||||
assert item in str(onion)
|
assert item in str(onion)
|
||||||
|
|
||||||
|
|
||||||
def test_not_valid_share_port(monkeypatch):
|
def test_not_valid_share_port(monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_SERVICE_NAME': 'group1',
|
'SERVICE1_SERVICE_NAME': 'group1',
|
||||||
|
@ -382,6 +390,7 @@ def test_not_valid_share_port(monkeypatch):
|
||||||
onion.check_services()
|
onion.check_services()
|
||||||
assert 'Same port for multiple services' in str(excinfo.value)
|
assert 'Same port for multiple services' in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
def test_not_valid_no_services(monkeypatch):
|
def test_not_valid_no_services(monkeypatch):
|
||||||
env = {
|
env = {
|
||||||
'SERVICE1_SERVICE_NAME': 'group1',
|
'SERVICE1_SERVICE_NAME': 'group1',
|
||||||
|
|
Loading…
Add table
Reference in a new issue