def test_get_vhosts(self): nparser = parser.NginxParser(self.config_path) vhosts = nparser.get_vhosts() vhost1 = obj.VirtualHost(nparser.abs_path('nginx.conf'), [obj.Addr('', '8080', False, False, False, False)], False, True, set(['localhost', r'~^(www\.)?(example|bar)\.']), [], [10, 1, 9]) vhost2 = obj.VirtualHost(nparser.abs_path('nginx.conf'), [obj.Addr('somename', '8080', False, False, False, False), obj.Addr('', '8000', False, False, False, False)], False, True, set(['somename', 'another.alias', 'alias']), [], [10, 1, 12]) vhost3 = obj.VirtualHost(nparser.abs_path('sites-enabled/example.com'), [obj.Addr('69.50.225.155', '9000', False, False, False, False), obj.Addr('127.0.0.1', '', False, False, False, False)], False, True, set(['.example.com', 'example.*']), [], [0]) vhost4 = obj.VirtualHost(nparser.abs_path('sites-enabled/default'), [obj.Addr('myhost', '', False, True, False, False), obj.Addr('otherhost', '', False, True, False, False)], False, True, set(['www.example.org']), [], [0]) vhost5 = obj.VirtualHost(nparser.abs_path('foo.conf'), [obj.Addr('*', '80', True, True, False, False)], True, True, set(['*.www.foo.com', '*.www.example.com']), [], [2, 1, 0]) self.assertEqual(13, len(vhosts)) example_com = [x for x in vhosts if 'example.com' in x.filep][0] self.assertEqual(vhost3, example_com) default = [x for x in vhosts if 'default' in x.filep][0] self.assertEqual(vhost4, default) fooconf = [x for x in vhosts if 'foo.conf' in x.filep][0] self.assertEqual(vhost5, fooconf) localhost = [x for x in vhosts if 'localhost' in x.names][0] self.assertEqual(vhost1, localhost) somename = [x for x in vhosts if 'somename' in x.names][0] self.assertEqual(vhost2, somename)
def get_vhosts(self): # pylint: disable=cell-var-from-loop """Gets list of all 'virtual hosts' found in Nginx configuration. Technically this is a misnomer because Nginx does not have virtual hosts, it has 'server blocks'. :returns: List of :class:`~certbot_nginx.obj.VirtualHost` objects found in configuration :rtype: list """ enabled = True # We only look at enabled vhosts for now servers = self._get_raw_servers() vhosts = [] for filename in servers: for server, path in servers[filename]: # Parse the server block into a VirtualHost object parsed_server = _parse_server_raw(server) vhost = obj.VirtualHost(filename, parsed_server['addrs'], parsed_server['ssl'], enabled, parsed_server['names'], server, path) vhosts.append(vhost) self._update_vhosts_addrs_ssl(vhosts) return vhosts
def test_has_ssl_on_directive(self): nparser = parser.NginxParser(self.config_path) mock_vhost = obj.VirtualHost( None, None, None, None, None, [['listen', 'myhost default_server'], ['server_name', 'www.example.org'], [['location', '/'], [['root', 'html'], ['index', 'index.html index.htm']]]], None) self.assertFalse(nparser.has_ssl_on_directive(mock_vhost)) mock_vhost.raw = [['listen', '*:80', 'default_server', 'ssl'], [ 'server_name', '*.www.foo.com', '*.www.example.com' ], ['root', '/home/ubuntu/sites/foo/']] self.assertFalse(nparser.has_ssl_on_directive(mock_vhost)) mock_vhost.raw = [['listen', '80 ssl'], [ 'server_name', '*.www.foo.com', '*.www.example.com' ]] self.assertFalse(nparser.has_ssl_on_directive(mock_vhost)) mock_vhost.raw = [['listen', '80'], ['ssl', 'on'], [ 'server_name', '*.www.foo.com', '*.www.example.com' ]] self.assertTrue(nparser.has_ssl_on_directive(mock_vhost))
def test_replace_server_directives(self): nparser = parser.NginxParser(self.config_path) target = set(['.example.com', 'example.*']) filep = nparser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(filep, None, None, None, target, None, [0]) nparser.add_server_directives(mock_vhost, [['server_name', 'foobar.com']], replace=True) from certbot_nginx.parser import COMMENT self.assertEqual( nparser.parsed[filep], [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', 'foobar.com'], ['#', COMMENT], ['server_name', 'example.*'], []]]]) mock_vhost.names = set(['foobar.com', 'example.*']) nparser.add_server_directives(mock_vhost, [['ssl_certificate', 'cert.pem']], replace=True) self.assertEqual(nparser.parsed[filep], [[['server'], [ ['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', 'foobar.com'], ['#', COMMENT], ['server_name', 'example.*'], [], ['ssl_certificate', 'cert.pem'], ['#', COMMENT], [], ]]])
def test_comment_is_repeatable(self): nparser = parser.NginxParser(self.config_path) example_com = nparser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(example_com, None, None, None, set(['.example.com', 'example.*']), None, [0]) nparser.add_server_directives(mock_vhost, [['\n ', '#', ' ', 'what a nice comment']], replace=False) nparser.add_server_directives(mock_vhost, [['\n ', 'include', ' ', nparser.abs_path('comment_in_file.conf')]], replace=False) from certbot_nginx.parser import COMMENT self.assertEqual(nparser.parsed[example_com], [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], ['#', ' ', 'what a nice comment'], [], ['include', nparser.abs_path('comment_in_file.conf')], ['#', COMMENT], []]]] )
def test_get_vhosts_global_ssl(self): nparser = parser.NginxParser(self.config_path, self.ssl_options) vhosts = nparser.get_vhosts() vhost = obj.VirtualHost(nparser.abs_path('sites-enabled/globalssl.com'), [obj.Addr('4.8.2.6', '57', True, False)], True, True, set(['globalssl.com']), [], [0]) globalssl_com = [x for x in vhosts if 'globalssl.com' in x.filep][0] self.assertEqual(vhost, globalssl_com)
def test_add_server_directives(self): nparser = parser.NginxParser(self.config_path, self.ssl_options) mock_vhost = obj.VirtualHost(nparser.abs_path('nginx.conf'), None, None, None, set(['localhost', r'~^(www\.)?(example|bar)\.']), None, [10, 1, 9]) nparser.add_server_directives(mock_vhost, [['foo', 'bar'], ['\n ', 'ssl_certificate', ' ', '/etc/ssl/cert.pem']], replace=False) ssl_re = re.compile(r'\n\s+ssl_certificate /etc/ssl/cert.pem') dump = nginxparser.dumps(nparser.parsed[nparser.abs_path('nginx.conf')]) self.assertEqual(1, len(re.findall(ssl_re, dump))) example_com = nparser.abs_path('sites-enabled/example.com') names = set(['.example.com', 'example.*']) mock_vhost.filep = example_com mock_vhost.names = names mock_vhost.path = [0] nparser.add_server_directives(mock_vhost, [['foo', 'bar'], ['ssl_certificate', '/etc/ssl/cert2.pem']], replace=False) nparser.add_server_directives(mock_vhost, [['foo', 'bar']], replace=False) from certbot_nginx.parser import COMMENT self.assertEqual(nparser.parsed[example_com], [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], ['foo', 'bar'], ['#', COMMENT], ['ssl_certificate', '/etc/ssl/cert2.pem'], ['#', COMMENT], [], [] ]]]) server_conf = nparser.abs_path('server.conf') names = set(['alias', 'another.alias', 'somename']) mock_vhost.filep = server_conf mock_vhost.names = names mock_vhost.path = [] self.assertRaises(errors.MisconfigurationError, nparser.add_server_directives, mock_vhost, [['foo', 'bar'], ['ssl_certificate', '/etc/ssl/cert2.pem']], replace=False)
def test_save(self): filep = self.config.parser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(filep, None, None, None, set(['.example.com', 'example.*']), None, [0]) self.config.parser.add_server_directives( mock_vhost, [['listen', ' ', '5001', ' ', 'ssl']]) self.config.save() # pylint: disable=protected-access parsed = self.config.parser._parse_files(filep, override=True) self.assertEqual( [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], ['listen', '5001', 'ssl'], ['#', parser.COMMENT]]]], parsed[0])
def test_get_all_certs_keys(self): nparser = parser.NginxParser(self.config_path, self.ssl_options) filep = nparser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(filep, None, None, None, set(['.example.com', 'example.*']), None, [0]) nparser.add_server_directives( mock_vhost, [['ssl_certificate', 'foo.pem'], ['ssl_certificate_key', 'bar.key'], ['listen', '443 ssl']], replace=False) c_k = nparser.get_all_certs_keys() migration_file = nparser.abs_path('sites-enabled/migration.com') self.assertEqual( set([('foo.pem', 'bar.key', filep), ('cert.pem', 'cert.key', migration_file)]), c_k)
def get_vhosts(self): # pylint: disable=cell-var-from-loop """Gets list of all 'virtual hosts' found in Nginx configuration. Technically this is a misnomer because Nginx does not have virtual hosts, it has 'server blocks'. :returns: List of :class:`~certbot_nginx.obj.VirtualHost` objects found in configuration :rtype: list """ enabled = True # We only look at enabled vhosts for now vhosts = [] servers = {} for filename in self.parsed: tree = self.parsed[filename] servers[filename] = [] srv = servers[filename] # workaround undefined loop var in lambdas # Find all the server blocks _do_for_subarray(tree, lambda x: x[0] == ['server'], lambda x, y: srv.append((x[1], y))) # Find 'include' statements in server blocks and append their trees for i, (server, path) in enumerate(servers[filename]): new_server = self._get_included_directives(server) servers[filename][i] = (new_server, path) for filename in servers: for server, path in servers[filename]: # Parse the server block into a VirtualHost object parsed_server = parse_server(server) vhost = obj.VirtualHost(filename, parsed_server['addrs'], parsed_server['ssl'], enabled, parsed_server['names'], server, path) vhosts.append(vhost) return vhosts
def choose_vhost(self, target_name): """Chooses a virtual host based on the given domain name. .. note:: This makes the vhost SSL-enabled if it isn't already. Follows Nginx's server block selection rules preferring blocks that are already SSL. .. todo:: This should maybe return list if no obvious answer is presented. .. todo:: The special name "$hostname" corresponds to the machine's hostname. Currently we just ignore this. :param str target_name: domain name :returns: ssl vhost associated with name :rtype: :class:`~certbot_nginx.obj.VirtualHost` """ vhost = None matches = self._get_ranked_matches(target_name) if not matches: # No matches. Create a new vhost with this name in nginx.conf. filep = self.parser.loc["root"] new_block = [['server'], [['\n', 'server_name', ' ', target_name]]] self.parser.add_http_directives(filep, new_block) vhost = obj.VirtualHost(filep, set([]), False, True, set([target_name]), list(new_block[1])) elif matches[0]['rank'] in xrange(2, 6): # Wildcard match - need to find the longest one rank = matches[0]['rank'] wildcards = [x for x in matches if x['rank'] == rank] vhost = max(wildcards, key=lambda x: len(x['name']))['vhost'] else: vhost = matches[0]['vhost'] if vhost is not None: if not vhost.ssl: self._make_server_ssl(vhost) return vhost
def test_remove_server_directives(self): nparser = parser.NginxParser(self.config_path) mock_vhost = obj.VirtualHost( nparser.abs_path('nginx.conf'), None, None, None, set(['localhost', r'~^(www\.)?(example|bar)\.']), None, [10, 1, 9]) example_com = nparser.abs_path('sites-enabled/example.com') names = set(['.example.com', 'example.*']) mock_vhost.filep = example_com mock_vhost.names = names mock_vhost.path = [0] nparser.add_server_directives( mock_vhost, [['foo', 'bar'], ['ssl_certificate', '/etc/ssl/cert2.pem']]) nparser.remove_server_directives(mock_vhost, 'foo') nparser.remove_server_directives(mock_vhost, 'ssl_certificate') self.assertEqual( nparser.parsed[example_com], [[['server'], [['listen', '69.50.225.155:9000'], ['listen', '127.0.0.1'], ['server_name', '.example.com'], ['server_name', 'example.*'], []]]])