Skip to content

Commit

Permalink
Merge pull request #2515 from vyos/mergify/bp/sagitta/pr-2508
Browse files Browse the repository at this point in the history
http: T5762: api: make API socket backend communication the one and only default (backport #2508)
  • Loading branch information
c-po authored Nov 20, 2023
2 parents 0650054 + 3280a15 commit 03740f1
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 43 deletions.
4 changes: 0 additions & 4 deletions data/templates/https/nginx.default.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ server {
# proxy settings for HTTP API, if enabled; 503, if not
location ~ ^/(retrieve|configure|config-file|image|container-image|generate|show|reset|docs|openapi.json|redoc|graphql) {
{% if server.api %}
{% if server.api.socket %}
proxy_pass http://unix:/run/api.sock;
{% else %}
proxy_pass http://localhost:{{ server.api.port }};
{% endif %}
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600;
Expand Down
7 changes: 0 additions & 7 deletions interface-definitions/https.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
<priority>1002</priority>
</properties>
<children>
#include <include/port-number.xml.i>
<node name="keys">
<properties>
<help>HTTP API keys</help>
Expand Down Expand Up @@ -101,12 +100,6 @@
<hidden/>
</properties>
</leafNode>
<leafNode name="socket">
<properties>
<help>Run server on Unix domain socket</help>
<valueless/>
</properties>
</leafNode>
<node name="graphql">
<properties>
<help>GraphQL support</help>
Expand Down
2 changes: 1 addition & 1 deletion interface-definitions/include/version/https-version.xml.i
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- include start from include/version/https-version.xml.i -->
<syntaxVersion component='https' version='4'></syntaxVersion>
<syntaxVersion component='https' version='5'></syntaxVersion>
<!-- include end -->
12 changes: 12 additions & 0 deletions smoketest/config-tests/basic-api-service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set interfaces ethernet eth0 address '192.0.2.1/31'
set interfaces ethernet eth0 address '2001:db8::1234/64'
set interfaces loopback lo
set service ntp server time1.vyos.net
set service ntp server time2.vyos.net
set service ntp server time3.vyos.net
set service https api keys id 1 key 'S3cur3'
set system config-management commit-revisions '100'
set system host-name 'vyos'
set system login user vyos authentication encrypted-password '$6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/'
set system login user vyos authentication plaintext-password ''
set system console device ttyS0 speed '115200'
66 changes: 66 additions & 0 deletions smoketest/configs/basic-api-service
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
interfaces {
ethernet eth0 {
address 192.0.2.1/31
address 2001:db8::1234/64
}
ethernet eth1 {
}
loopback lo {
}
}
service {
https {
api {
keys {
id 1 {
key S3cur3
}
}
socket
}
}
ssh {
}
}
system {
config-management {
commit-revisions 100
}
console {
device ttyS0 {
speed 115200
}
}
host-name vyos
login {
user vyos {
authentication {
encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/
plaintext-password ""
}
}
}
ntp {
server time1.vyos.net {
}
server time2.vyos.net {
}
server time3.vyos.net {
}
}
syslog {
global {
facility all {
level info
}
facility protocols {
level debug
}
}
}
}


// Warning: Do not remove the following line.
// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@1:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@13:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@6:salt@1:snmp@2:ssh@2:sstp@3:system@19:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webgui@1:webproxy@2:zone-policy@1"
// Release version: 1.3-rolling-202010241631
31 changes: 14 additions & 17 deletions smoketest/scripts/cli/test_service_https.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from base_vyostest_shim import VyOSUnitTestSHIM
from base_vyostest_shim import ignore_warning
from vyos.utils.file import read_file
from vyos.utils.process import run
from vyos.utils.process import process_named_running

base_path = ['service', 'https']
pki_base = ['pki']
Expand All @@ -49,24 +49,28 @@
u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww
"""

PROCESS_NAME = 'nginx'

class TestHTTPSService(VyOSUnitTestSHIM.TestCase):
def setUp(self):
@classmethod
def setUpClass(cls):
super(TestHTTPSService, cls).setUpClass()

# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
self.cli_delete(base_path)
self.cli_delete(pki_base)
cls.cli_delete(cls, base_path)
cls.cli_delete(cls, pki_base)

def tearDown(self):
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))

self.cli_delete(base_path)
self.cli_delete(pki_base)
self.cli_commit()

def test_default(self):
self.cli_set(base_path)
self.cli_commit()

ret = run('sudo /usr/sbin/nginx -t')
self.assertEqual(ret, 0)
# Check for stopped process
self.assertFalse(process_named_running(PROCESS_NAME))

def test_server_block(self):
vhost_id = 'example'
Expand All @@ -82,9 +86,6 @@ def test_server_block(self):

self.cli_commit()

ret = run('sudo /usr/sbin/nginx -t')
self.assertEqual(ret, 0)

nginx_config = read_file('/etc/nginx/sites-enabled/default')
self.assertIn(f'listen {address}:{port} ssl;', nginx_config)
self.assertIn(f'ssl_protocols TLSv1.2 TLSv1.3;', nginx_config)
Expand All @@ -97,17 +98,13 @@ def test_certificate(self):

self.cli_commit()

ret = run('sudo /usr/sbin/nginx -t')
self.assertEqual(ret, 0)

@ignore_warning(InsecureRequestWarning)
def test_api_auth(self):
vhost_id = 'example'
address = '127.0.0.1'
port = '443'
name = 'localhost'

self.cli_set(base_path + ['api', 'socket'])
key = 'MySuperSecretVyOS'
self.cli_set(base_path + ['api', 'keys', 'id', 'key-01', 'key', key])

Expand Down
5 changes: 0 additions & 5 deletions src/conf_mode/https.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,9 @@ def generate(https):
api_data = vyos.defaults.api_data
api_settings = https.get('api', {})
if api_settings:
port = api_settings.get('port', '')
if port:
api_data['port'] = port
vhosts = https.get('api-restrict', {}).get('virtual-host', [])
if vhosts:
api_data['vhost'] = vhosts[:]
if 'socket' in list(api_settings):
api_data['socket'] = True

if api_data:
vhost_list = api_data.get('vhost', [])
Expand Down
8 changes: 8 additions & 0 deletions src/etc/sysctl.d/30-vyos-router.conf
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,11 @@ net.core.rps_sock_flow_entries = 32768
net.core.default_qdisc=fq_codel
net.ipv4.tcp_congestion_control=bbr

# VRF - Virtual routing and forwarding
# When net.vrf.strict_mode=0 (default) it is possible to associate multiple
# VRF devices to the same table. Conversely, when net.vrf.strict_mode=1 a
# table can be associated to a single VRF device.
#
# A VRF table can be used by the VyOS CLI only once (ensured by verify()),
# this simply adds an additional Kernel safety net
net.vrf.strict_mode=1
56 changes: 56 additions & 0 deletions src/migration-scripts/https/4-to-5
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python3
#
# Copyright (C) 2023 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

# T5762: http: api: smoketests fail as they can not establish IPv6 connection
# to uvicorn backend server, always make the UNIX domain socket the
# default way of communication

import sys

from vyos.configtree import ConfigTree

if len(sys.argv) < 2:
print("Must specify file name!")
sys.exit(1)

file_name = sys.argv[1]

with open(file_name, 'r') as f:
config_file = f.read()

config = ConfigTree(config_file)

base = ['service', 'https']
if not config.exists(base):
# Nothing to do
sys.exit(0)

# Delete "socket" CLI option - we always use UNIX domain sockets for
# NGINX <-> API server communication
if config.exists(base + ['api', 'socket']):
config.delete(base + ['api', 'socket'])

# There is no need for an API service port, as UNIX domain sockets
# are used
if config.exists(base + ['api', 'port']):
config.delete(base + ['api', 'port'])

try:
with open(file_name, 'w') as f:
f.write(config.to_string())
except OSError as e:
print("Failed to save the modified config: {}".format(e))
sys.exit(1)
10 changes: 1 addition & 9 deletions src/services/vyos-http-api-server
Original file line number Diff line number Diff line change
Expand Up @@ -825,15 +825,7 @@ def initialization(session: ConfigSession, app: FastAPI = app):
if app.state.vyos_graphql:
graphql_init(app)

if not server_config['socket']:
config = ApiServerConfig(app,
host=server_config["listen_address"],
port=int(server_config["port"]),
proxy_headers=True)
else:
config = ApiServerConfig(app,
uds="/run/api.sock",
proxy_headers=True)
config = ApiServerConfig(app, uds="/run/api.sock", proxy_headers=True)
server = ApiServer(config)

def run_server():
Expand Down

0 comments on commit 03740f1

Please sign in to comment.