obj.py
1 """Module contains classes used by the Nginx Configurator.""" 2 import re 3 4 from letsencrypt.plugins import common 5 6 7 class Addr(common.Addr): 8 r"""Represents an Nginx address, i.e. what comes after the 'listen' 9 directive. 10 11 According to the `documentation`_, this may be address[:port], port, 12 or unix:path. The latter is ignored here. 13 14 The default value if no directive is specified is \*:80 (superuser) 15 or \*:8000 (otherwise). If no port is specified, the default is 16 80. If no address is specified, listen on all addresses. 17 18 .. _documentation: 19 http://nginx.org/en/docs/http/ngx_http_core_module.html#listen 20 21 .. todo:: Old-style nginx configs define SSL vhosts in a separate 22 block instead of using 'ssl' in the listen directive. 23 24 :param str addr: addr part of vhost address, may be hostname, IPv4, IPv6, 25 "", or "\*" 26 :param str port: port number or "\*" or "" 27 :param bool ssl: Whether the directive includes 'ssl' 28 :param bool default: Whether the directive includes 'default_server' 29 30 """ 31 def __init__(self, host, port, ssl, default): 32 super(Addr, self).__init__((host, port)) 33 self.ssl = ssl 34 self.default = default 35 36 @classmethod 37 def fromstring(cls, str_addr): 38 """Initialize Addr from string.""" 39 parts = str_addr.split(' ') 40 ssl = False 41 default = False 42 host = '' 43 port = '' 44 45 # The first part must be the address 46 addr = parts.pop(0) 47 48 # Ignore UNIX-domain sockets 49 if addr.startswith('unix:'): 50 return None 51 52 tup = addr.partition(':') 53 if re.match(r'^\d+$', tup[0]): 54 # This is a bare port, not a hostname. E.g. listen 80 55 host = '' 56 port = tup[0] 57 else: 58 # This is a host-port tuple. E.g. listen 127.0.0.1:* 59 host = tup[0] 60 port = tup[2] 61 62 # The rest of the parts are options; we only care about ssl and default 63 while len(parts) > 0: 64 nextpart = parts.pop() 65 if nextpart == 'ssl': 66 ssl = True 67 elif nextpart == 'default_server': 68 default = True 69 70 return cls(host, port, ssl, default) 71 72 def __str__(self): 73 parts = '' 74 if self.tup[0] and self.tup[1]: 75 parts = "%s:%s" % self.tup 76 elif self.tup[0]: 77 parts = self.tup[0] 78 else: 79 parts = self.tup[1] 80 81 if self.default: 82 parts += ' default_server' 83 if self.ssl: 84 parts += ' ssl' 85 86 return parts 87 88 def __eq__(self, other): 89 if isinstance(other, self.__class__): 90 return (self.tup == other.tup and 91 self.ssl == other.ssl and 92 self.default == other.default) 93 return False 94 95 96 class VirtualHost(object): # pylint: disable=too-few-public-methods 97 """Represents an Nginx Virtualhost. 98 99 :ivar str filep: file path of VH 100 :ivar set addrs: Virtual Host addresses (:class:`set` of :class:`Addr`) 101 :ivar set names: Server names/aliases of vhost 102 (:class:`list` of :class:`str`) 103 :ivar list raw: The raw form of the parsed server block 104 105 :ivar bool ssl: SSLEngine on in vhost 106 :ivar bool enabled: Virtual host is enabled 107 108 """ 109 110 def __init__(self, filep, addrs, ssl, enabled, names, raw): 111 # pylint: disable=too-many-arguments 112 """Initialize a VH.""" 113 self.filep = filep 114 self.addrs = addrs 115 self.names = names 116 self.ssl = ssl 117 self.enabled = enabled 118 self.raw = raw 119 120 def __str__(self): 121 addr_str = ", ".join(str(addr) for addr in self.addrs) 122 return ("file: %s\n" 123 "addrs: %s\n" 124 "names: %s\n" 125 "ssl: %s\n" 126 "enabled: %s" % (self.filep, addr_str, 127 self.names, self.ssl, self.enabled)) 128 129 def __eq__(self, other): 130 if isinstance(other, self.__class__): 131 return (self.filep == other.filep and 132 list(self.addrs) == list(other.addrs) and 133 self.names == other.names and 134 self.ssl == other.ssl and self.enabled == other.enabled) 135 136 return False