mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-02-18 08:33:41 +00:00
tor: Use augeas to modify configuration.
- Use json to get info from action script. - Add SSH port to hidden service. - Enable hidden service during setup.
This commit is contained in:
parent
cd82188efd
commit
a6417c59a7
195
actions/tor
195
actions/tor
@ -22,7 +22,9 @@ Configuration helper for the Tor service
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import augeas
|
||||
import codecs
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
@ -33,7 +35,7 @@ from plinth.modules.tor import is_enabled, is_running, get_augeas, \
|
||||
get_real_apt_uri_path, iter_apt_uris, APT_TOR_PREFIX
|
||||
|
||||
SERVICE_FILE = '/etc/firewalld/services/tor-{0}.xml'
|
||||
TOR_CONFIG = '/etc/tor/torrc'
|
||||
TOR_CONFIG = '/files/etc/tor/torrc'
|
||||
TOR_STATE_FILE = '/var/lib/tor/state'
|
||||
TOR_AUTH_COOKIE = '/var/run/tor/control.authcookie'
|
||||
|
||||
@ -44,8 +46,10 @@ def parse_arguments():
|
||||
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||
|
||||
subparsers.add_parser('setup', help='Setup Tor configuration')
|
||||
subparsers.add_parser('get-ports', help='Get list of Tor ports')
|
||||
subparsers.add_parser('get-hs', help='Get hidden service')
|
||||
subparsers.add_parser('get-ports',
|
||||
help='Get Tor ports in JSON format')
|
||||
subparsers.add_parser('get-hs',
|
||||
help='Get hidden service information in JSON format')
|
||||
|
||||
configure = subparsers.add_parser('configure', help='Configure Tor')
|
||||
configure.add_argument('--service', choices=['enable', 'disable'],
|
||||
@ -61,50 +65,63 @@ def parse_arguments():
|
||||
|
||||
def subcommand_setup(_):
|
||||
"""Setup Tor configuration after installing it."""
|
||||
# XXX: Performing this as a post-install step instead of
|
||||
# pre-install setup for now. Creating a configuration before hand
|
||||
# leads dpkg to ask question about configuration overwrite which
|
||||
# makes aptcc backend of packagekit to wait forever even with
|
||||
# interactive=False.
|
||||
lines = """
|
||||
# Run as non-exit bridge relay
|
||||
SocksPort [::]:9050
|
||||
SocksPort 0.0.0.0:9050
|
||||
ORPort auto
|
||||
ControlPort 9051
|
||||
BridgeRelay 1
|
||||
Exitpolicy reject *:*
|
||||
Exitpolicy reject6 *:*
|
||||
aug = augeas_load()
|
||||
|
||||
# Enable obfsproxy
|
||||
ServerTransportPlugin obfs3,obfs4 exec /usr/bin/obfs4proxy
|
||||
ExtORPort auto
|
||||
aug.set(TOR_CONFIG + '/#comment[last() + 1]',
|
||||
'Run as non-exit bridge relay')
|
||||
aug.set(TOR_CONFIG + '/SocksPort[1]', '[::]:9050')
|
||||
aug.set(TOR_CONFIG + '/SocksPort[2]', '0.0.0.0:9050')
|
||||
aug.set(TOR_CONFIG + '/ORPort', 'auto')
|
||||
aug.set(TOR_CONFIG + '/ControlPort', '9051')
|
||||
aug.set(TOR_CONFIG + '/BridgeRelay', '1')
|
||||
aug.set(TOR_CONFIG + '/ExitPolicy[1]', 'reject *:*')
|
||||
aug.set(TOR_CONFIG + '/ExitPolicy[2]', 'reject6 *:*')
|
||||
|
||||
# Enable transparent proxy
|
||||
VirtualAddrNetworkIPv4 10.192.0.0/10
|
||||
AutomapHostsOnResolve 1
|
||||
TransPort 127.0.0.1:9040
|
||||
TransPort [::1]:9040
|
||||
DNSPort 127.0.0.1:9053
|
||||
DNSPort [::1]:9053
|
||||
"""
|
||||
with open(TOR_CONFIG, 'w') as conffile:
|
||||
conffile.writelines(lines)
|
||||
aug.set(TOR_CONFIG + '/#comment[last() + 1]', 'Enable obfsproxy')
|
||||
aug.set(TOR_CONFIG + '/ServerTransportPlugin',
|
||||
'obfs3,obfs4 exec /usr/bin/obfs4proxy')
|
||||
aug.set(TOR_CONFIG + '/ExtORPort', 'auto')
|
||||
|
||||
aug.set(TOR_CONFIG + '/#comment[last() + 1]', 'Enable transparent proxy')
|
||||
aug.set(TOR_CONFIG + '/VirtualAddrNetworkIPv4', '10.192.0.0/10')
|
||||
aug.set(TOR_CONFIG + '/AutomapHostsOnResolve', '1')
|
||||
aug.set(TOR_CONFIG + '/TransPort[1]', '127.0.0.1:9040')
|
||||
aug.set(TOR_CONFIG + '/TransPort[2]', '[::1]:9040')
|
||||
aug.set(TOR_CONFIG + '/DNSPort[1]', '127.0.0.1:9053')
|
||||
aug.set(TOR_CONFIG + '/DNSPort[2]', '[::1]:9053')
|
||||
|
||||
aug.set(TOR_CONFIG + '/HiddenServiceDir',
|
||||
'/var/lib/tor/hidden_service')
|
||||
aug.set(TOR_CONFIG + '/HiddenServicePort[1]',
|
||||
'22 127.0.0.1:22')
|
||||
aug.set(TOR_CONFIG + '/HiddenServicePort[2]',
|
||||
'80 127.0.0.1:80')
|
||||
aug.set(TOR_CONFIG + '/HiddenServicePort[3]',
|
||||
'443 127.0.0.1:443')
|
||||
|
||||
aug.save()
|
||||
|
||||
action_utils.service_restart('tor')
|
||||
_update_ports()
|
||||
|
||||
# wait until hidden service information is available
|
||||
tries = 0
|
||||
while not get_hidden_service()['enabled']:
|
||||
tries += 1
|
||||
if tries >= 12:
|
||||
return
|
||||
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
def subcommand_get_ports(_):
|
||||
"""Get list of Tor ports."""
|
||||
ports = get_ports()
|
||||
for name, number in ports.items():
|
||||
print(name, number)
|
||||
"""Get Tor ports in JSON format."""
|
||||
print(json.dumps(get_ports()))
|
||||
|
||||
|
||||
def subcommand_get_hs(_):
|
||||
"""Print currently configured Tor hidden service information"""
|
||||
print(get_hidden_service())
|
||||
"""Get hidden service information in JSON format."""
|
||||
print(json.dumps(get_hidden_service()))
|
||||
|
||||
|
||||
def subcommand_configure(arguments):
|
||||
@ -171,29 +188,32 @@ QUIT
|
||||
|
||||
def get_hidden_service():
|
||||
"""Return a string with configured Tor hidden service information"""
|
||||
hs_dir = None
|
||||
hs_enabled = False
|
||||
hs_status = 'Ok'
|
||||
hs_hostname = None
|
||||
hs_ports = []
|
||||
|
||||
try:
|
||||
with open(TOR_CONFIG, 'r') as conf_file:
|
||||
for line in conf_file:
|
||||
if line.startswith('HiddenServiceDir'):
|
||||
hs_dir = line.split()[1]
|
||||
elif line.startswith('HiddenServicePort'):
|
||||
hs_ports.append(line.split()[1])
|
||||
except FileNotFoundError:
|
||||
return 'error'
|
||||
aug = augeas_load()
|
||||
hs_dir = aug.get(TOR_CONFIG + '/HiddenServiceDir')
|
||||
hs_port_paths = aug.match(TOR_CONFIG + '/HiddenServicePort')
|
||||
|
||||
for hs_port_path in hs_port_paths:
|
||||
port_info = aug.get(hs_port_path).split()
|
||||
hs_ports.append({'virtport': port_info[0],
|
||||
'target': port_info[1]})
|
||||
|
||||
if not hs_dir:
|
||||
return ''
|
||||
hs_status = 'Not Configured'
|
||||
else:
|
||||
try:
|
||||
with open(os.path.join(hs_dir, 'hostname'), 'r') as conf_file:
|
||||
hs_hostname = conf_file.read().strip()
|
||||
hs_enabled = True
|
||||
except Exception:
|
||||
hs_status = 'Not available (Run Tor at least once)'
|
||||
|
||||
try:
|
||||
with open(os.path.join(hs_dir, 'hostname'), 'r') as conf_file:
|
||||
hs_hostname = conf_file.read().strip()
|
||||
except Exception:
|
||||
return 'error'
|
||||
|
||||
return hs_hostname + ' ' + ','.join(hs_ports)
|
||||
return {'enabled': hs_enabled, 'status': hs_status,
|
||||
'hostname': hs_hostname, 'ports': hs_ports}
|
||||
|
||||
|
||||
def _enable():
|
||||
@ -210,20 +230,19 @@ def _disable():
|
||||
|
||||
def _enable_hs(restart=True):
|
||||
"""Enable Tor hidden service"""
|
||||
if get_hidden_service():
|
||||
if get_hidden_service()['enabled']:
|
||||
return
|
||||
|
||||
with open(TOR_CONFIG, 'r') as conffile:
|
||||
lines = conffile.readlines()
|
||||
|
||||
lines.append('# Hidden Service configured by Plinth\n')
|
||||
lines.append('HiddenServiceDir /var/lib/tor/hidden_service/\n')
|
||||
lines.append('HiddenServicePort 80 127.0.0.1:80\n')
|
||||
lines.append('HiddenServicePort 443 127.0.0.1:443\n')
|
||||
lines.append('# end of Plinth Hidden Service config\n')
|
||||
|
||||
with open(TOR_CONFIG, 'w') as conffile:
|
||||
conffile.writelines(lines)
|
||||
aug = augeas_load()
|
||||
aug.set(TOR_CONFIG + '/HiddenServiceDir',
|
||||
'/var/lib/tor/hidden_service')
|
||||
aug.set(TOR_CONFIG + '/HiddenServicePort[1]',
|
||||
'22 127.0.0.1:22')
|
||||
aug.set(TOR_CONFIG + '/HiddenServicePort[2]',
|
||||
'80 127.0.0.1:80')
|
||||
aug.set(TOR_CONFIG + '/HiddenServicePort[3]',
|
||||
'443 127.0.0.1:443')
|
||||
aug.save()
|
||||
|
||||
if restart:
|
||||
if is_enabled() and is_running():
|
||||
@ -231,7 +250,7 @@ def _enable_hs(restart=True):
|
||||
|
||||
# wait until hidden service information is available
|
||||
tries = 0
|
||||
while get_hidden_service() in ('', 'error'):
|
||||
while not get_hidden_service()['enabled']:
|
||||
tries += 1
|
||||
if tries >= 12:
|
||||
return
|
||||
@ -241,35 +260,13 @@ def _enable_hs(restart=True):
|
||||
|
||||
def _disable_hs(restart=True):
|
||||
"""Disable Tor hidden service"""
|
||||
if not get_hidden_service():
|
||||
if not get_hidden_service()['enabled']:
|
||||
return
|
||||
|
||||
with open(TOR_CONFIG, 'r') as conffile:
|
||||
lines = conffile.readlines()
|
||||
|
||||
filtered_lines = []
|
||||
removing = False
|
||||
for line in lines:
|
||||
if removing:
|
||||
if line.startswith('# end of Plinth Hidden Service config'):
|
||||
# last line of Plinth hidden service block
|
||||
# stop removing after this line
|
||||
removing = False
|
||||
elif not line.startswith('HiddenService'):
|
||||
# end of Plinth hidden service block
|
||||
# stop removing lines
|
||||
removing = False
|
||||
filtered_lines.append(line)
|
||||
else:
|
||||
if line.startswith('# Hidden Service configured by Plinth'):
|
||||
# start of Plinth hidden service block
|
||||
# remove following HiddenService lines
|
||||
removing = True
|
||||
else:
|
||||
filtered_lines.append(line)
|
||||
|
||||
with open(TOR_CONFIG, 'w') as conffile:
|
||||
conffile.writelines(filtered_lines)
|
||||
aug = augeas_load()
|
||||
aug.remove(TOR_CONFIG + '/HiddenServiceDir')
|
||||
aug.remove(TOR_CONFIG + '/HiddenServicePort')
|
||||
aug.save()
|
||||
|
||||
if restart:
|
||||
if is_enabled() and is_running():
|
||||
@ -347,6 +344,16 @@ def _update_ports():
|
||||
action_utils.service_restart('firewalld')
|
||||
|
||||
|
||||
def augeas_load():
|
||||
"""Initialize Augeas."""
|
||||
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||
aug.set('/augeas/load/Tor/lens', 'Tor.lns')
|
||||
aug.set('/augeas/load/Tor/incl[last() + 1]', '/etc/tor/torrc')
|
||||
aug.load()
|
||||
return aug
|
||||
|
||||
|
||||
def main():
|
||||
"""Parse arguments and perform all duties"""
|
||||
arguments = parse_arguments()
|
||||
|
||||
11
data/usr/share/augeas/lenses/tests/test_tor.aug
Normal file
11
data/usr/share/augeas/lenses/tests/test_tor.aug
Normal file
@ -0,0 +1,11 @@
|
||||
module Test_Tor =
|
||||
|
||||
test Tor.lns get "\n" = { }
|
||||
test Tor.lns get "# comment\n" = { "#comment" = "comment" }
|
||||
test Tor.lns get "SocksPort 9050\n" = { "SocksPort" = "9050" }
|
||||
test Tor.lns get "SocksPort 0.0.0.0:9050\n" = { "SocksPort" = "0.0.0.0:9050" }
|
||||
test Tor.lns get "SocksPort [::]:9050\n" = { "SocksPort" = "[::]:9050" }
|
||||
test Tor.lns get "ExitPolicy reject *:*\n" = { "ExitPolicy" = "reject *:*" }
|
||||
test Tor.lns get "VirtualAddrNetworkIPv4 10.192.0.0/10\n" = { "VirtualAddrNetworkIPv4" = "10.192.0.0/10" }
|
||||
test Tor.lns get "ServerTransportPlugin obfs3,obfs4 exec /usr/bin/obfs4proxy\n" = { "ServerTransportPlugin" = "obfs3,obfs4 exec /usr/bin/obfs4proxy" }
|
||||
test Tor.lns get "HiddenServiceDir /var/lib/tor/hidden_service/\n" = { "HiddenServiceDir" = "/var/lib/tor/hidden_service/" }
|
||||
36
data/usr/share/augeas/lenses/tor.aug
Normal file
36
data/usr/share/augeas/lenses/tor.aug
Normal file
@ -0,0 +1,36 @@
|
||||
(* Tor lens for Augeas
|
||||
|
||||
Author: James Valleroy <jvalleroy@mailbox.org>
|
||||
|
||||
About: Reference
|
||||
Online Tor configuration manual:
|
||||
https://www.torproject.org/docs/tor-manual.html.en
|
||||
|
||||
About: License
|
||||
This file is licensed under the LGPL v2+.
|
||||
|
||||
About: Configuration files
|
||||
This lens applies to /etc/tor/torrc. See <filter>.
|
||||
|
||||
*)
|
||||
|
||||
|
||||
module Tor =
|
||||
|
||||
autoload xfm
|
||||
|
||||
let eol = Util.eol
|
||||
|
||||
let ws = /[ \t]/
|
||||
let kc = /[A-Za-z0-9_.,:*]/
|
||||
let vc = /[A-Za-z0-9_.,:*\/ ]/
|
||||
let keyname = kc+
|
||||
let val = /[[\/]*/ . kc . (vc* . /[]]*/ . vc* . kc . /[\/]*/)?
|
||||
|
||||
let entry = [ key keyname . del ws+ " " . store val . eol ]
|
||||
|
||||
let lns = (entry|Util.comment|Util.empty_dos)*
|
||||
|
||||
let filter = (incl "/etc/tor/torrc")
|
||||
|
||||
let xfm = transform lns filter
|
||||
@ -23,13 +23,14 @@ import augeas
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import glob
|
||||
import itertools
|
||||
import json
|
||||
|
||||
from plinth import actions
|
||||
from plinth import action_utils
|
||||
from plinth import cfg
|
||||
from plinth import service as service_module
|
||||
from plinth.modules.names import SERVICES
|
||||
from plinth.signals import domain_added
|
||||
from plinth.signals import domain_added, domain_removed
|
||||
|
||||
|
||||
version = 1
|
||||
@ -72,20 +73,23 @@ def init():
|
||||
is_external=True, enabled=is_enabled())
|
||||
|
||||
# Register hidden service name with Name Services module.
|
||||
(hs_enabled, hs_hostname, hs_ports) = get_hs()
|
||||
hs_info = get_hs()
|
||||
hostname = hs_info['hostname']
|
||||
hs_virtports = [port['virtport'] for port in hs_info['ports']]
|
||||
|
||||
if is_enabled() and is_running() and hs_enabled and hs_hostname:
|
||||
if is_enabled() and is_running() and \
|
||||
hs_info['enabled'] and hs_info['hostname']:
|
||||
hs_services = []
|
||||
for service_type in SERVICES:
|
||||
if str(service_type[2]) in hs_ports:
|
||||
if str(service_type[2]) in hs_virtports:
|
||||
hs_services.append(service_type[0])
|
||||
else:
|
||||
hs_hostname = None
|
||||
hostname = None
|
||||
hs_services = None
|
||||
|
||||
domain_added.send_robust(
|
||||
sender='tor', domain_type='hiddenservice',
|
||||
name=hs_hostname, description=_('Tor Hidden Service'),
|
||||
name=hostname, description=_('Tor Hidden Service'),
|
||||
services=hs_services)
|
||||
|
||||
|
||||
@ -98,6 +102,23 @@ def setup(helper, old_version=None):
|
||||
['configure', '--apt-transport-tor', 'enable'])
|
||||
helper.call('post', socks_service.notify_enabled, None, True)
|
||||
helper.call('post', bridge_service.notify_enabled, None, True)
|
||||
helper.call('post', update_hidden_service_domain)
|
||||
|
||||
|
||||
def update_hidden_service_domain(status=None):
|
||||
"""Update HS domain with Name Services module."""
|
||||
if not status:
|
||||
status = get_status()
|
||||
|
||||
domain_removed.send_robust(
|
||||
sender='tor', domain_type='hiddenservice')
|
||||
|
||||
if status['enabled'] and status['is_running'] and \
|
||||
status['hs_enabled'] and status['hs_hostname']:
|
||||
domain_added.send_robust(
|
||||
sender='tor', domain_type='hiddenservice',
|
||||
name=status['hs_hostname'], description=_('Tor Hidden Service'),
|
||||
services=status['hs_services'])
|
||||
|
||||
|
||||
def is_enabled():
|
||||
@ -113,45 +134,30 @@ def is_running():
|
||||
def get_status():
|
||||
"""Return current Tor status."""
|
||||
output = actions.superuser_run('tor', ['get-ports'])
|
||||
port_info = output.split('\n')
|
||||
ports = {}
|
||||
for line in port_info:
|
||||
try:
|
||||
(key, val) = line.split()
|
||||
ports[key] = val
|
||||
except ValueError:
|
||||
continue
|
||||
ports = json.loads(output)
|
||||
|
||||
(hs_enabled, hs_hostname, hs_ports) = get_hs()
|
||||
hs_info = get_hs()
|
||||
hs_services = []
|
||||
hs_virtports = [port['virtport'] for port in hs_info['ports']]
|
||||
for service_type in SERVICES:
|
||||
if str(service_type[2]) in hs_virtports:
|
||||
hs_services.append(service_type[0])
|
||||
|
||||
return {'enabled': is_enabled(),
|
||||
'is_running': is_running(),
|
||||
'ports': ports,
|
||||
'hs_enabled': hs_enabled,
|
||||
'hs_hostname': hs_hostname,
|
||||
'hs_ports': hs_ports,
|
||||
'hs_enabled': hs_info['enabled'],
|
||||
'hs_status': hs_info['status'],
|
||||
'hs_hostname': hs_info['hostname'],
|
||||
'hs_ports': hs_info['ports'],
|
||||
'hs_services': hs_services,
|
||||
'apt_transport_tor_enabled': is_apt_transport_tor_enabled()}
|
||||
|
||||
|
||||
def get_hs():
|
||||
"""Return hidden service status."""
|
||||
output = actions.superuser_run('tor', ['get-hs'])
|
||||
output = output.strip()
|
||||
if output == '':
|
||||
hs_enabled = False
|
||||
hs_hostname = 'Not Configured'
|
||||
hs_ports = ''
|
||||
elif output == 'error':
|
||||
hs_enabled = False
|
||||
hs_hostname = 'Not available (Run Tor at least once)'
|
||||
hs_ports = ''
|
||||
else:
|
||||
hs_enabled = True
|
||||
hs_info = output.split()
|
||||
hs_hostname = hs_info[0]
|
||||
hs_ports = hs_info[1]
|
||||
|
||||
return (hs_enabled, hs_hostname, hs_ports)
|
||||
return json.loads(output)
|
||||
|
||||
|
||||
def get_augeas():
|
||||
@ -239,8 +245,7 @@ def diagnose():
|
||||
results.extend(_diagnose_control_port())
|
||||
|
||||
output = actions.superuser_run('tor', ['get-ports'])
|
||||
ports = [line.split() for line in output.splitlines()]
|
||||
ports = {port_type: int(port) for port_type, port in ports}
|
||||
ports = json.loads(output)
|
||||
|
||||
results.append([_('Tor relay port available'),
|
||||
'passed' if 'orport' in ports else 'failed'])
|
||||
|
||||
@ -62,13 +62,19 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Hidden Service" %}</th>
|
||||
<th>{% trans "Port" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Ports" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ status.hs_hostname }}</td>
|
||||
<td>{{ status.hs_ports }}</td>
|
||||
<td>{{ status.hs_status }}</td>
|
||||
<td>
|
||||
{% for service in status.hs_services %}
|
||||
{{ service }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@ -27,8 +27,6 @@ from .forms import TorForm
|
||||
from plinth import actions
|
||||
from plinth.errors import ActionError
|
||||
from plinth.modules import tor
|
||||
from plinth.modules.names import SERVICES
|
||||
from plinth.signals import domain_added, domain_removed
|
||||
|
||||
config_process = None
|
||||
|
||||
@ -115,22 +113,7 @@ def _collect_config_result(request):
|
||||
|
||||
tor.socks_service.notify_enabled(None, status['enabled'])
|
||||
tor.bridge_service.notify_enabled(None, status['enabled'])
|
||||
|
||||
# Update hidden service name registered with Name Services module.
|
||||
domain_removed.send_robust(
|
||||
sender='tor', domain_type='hiddenservice')
|
||||
|
||||
if status['enabled'] and status['is_running'] and \
|
||||
status['hs_enabled'] and status['hs_hostname']:
|
||||
hs_services = []
|
||||
for service in SERVICES:
|
||||
if str(service[2]) in status['hs_ports']:
|
||||
hs_services.append(service[0])
|
||||
|
||||
domain_added.send_robust(
|
||||
sender='tor', domain_type='hiddenservice',
|
||||
name=status['hs_hostname'], description=_('Tor Hidden Service'),
|
||||
services=hs_services)
|
||||
tor.update_hidden_service_domain(status)
|
||||
|
||||
if not return_code:
|
||||
messages.success(request, _('Configuration updated.'))
|
||||
|
||||
4
setup.py
4
setup.py
@ -214,9 +214,9 @@ setuptools.setup(
|
||||
('/usr/share/man/man1', ['doc/plinth.1']),
|
||||
('/etc/plinth', ['data/etc/plinth/plinth.config']),
|
||||
('/usr/share/augeas/lenses',
|
||||
['data/usr/share/augeas/lenses/pagekite.aug']),
|
||||
glob.glob('data/usr/share/augeas/lenses/*.aug')),
|
||||
('/usr/share/augeas/lenses/tests',
|
||||
['data/usr/share/augeas/lenses/tests/test_pagekite.aug']),
|
||||
glob.glob('data/usr/share/augeas/lenses/tests/test_*.aug')),
|
||||
('/etc/plinth/modules-enabled',
|
||||
glob.glob(os.path.join('data/etc/plinth/modules-enabled',
|
||||
'*')))],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user