gns3-server 3.0.1__py3-none-any.whl → 3.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of gns3-server might be problematic. Click here for more details.

Files changed (30) hide show
  1. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/METADATA +22 -21
  2. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/RECORD +29 -27
  3. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/WHEEL +1 -1
  4. gns3server/api/routes/compute/iou_nodes.py +1 -1
  5. gns3server/api/routes/controller/images.py +58 -21
  6. gns3server/api/routes/controller/templates.py +23 -2
  7. gns3server/appliances/alpine-cloud.gns3a +56 -0
  8. gns3server/appliances/stormshield-eva.gns3a +50 -0
  9. gns3server/compute/docker/__init__.py +1 -1
  10. gns3server/compute/virtualbox/virtualbox_vm.py +29 -25
  11. gns3server/controller/__init__.py +27 -18
  12. gns3server/controller/appliance_manager.py +2 -2
  13. gns3server/controller/compute.py +7 -2
  14. gns3server/crash_report.py +1 -1
  15. gns3server/db/repositories/images.py +22 -3
  16. gns3server/db/repositories/templates.py +11 -0
  17. gns3server/db/tasks.py +120 -79
  18. gns3server/main.py +40 -2
  19. gns3server/server.py +26 -41
  20. gns3server/services/authentication.py +9 -6
  21. gns3server/static/web-ui/index.html +1 -1
  22. gns3server/static/web-ui/main.2e807eb4bc32f838.js +1 -0
  23. gns3server/utils/asyncio/__init__.py +4 -12
  24. gns3server/utils/asyncio/pool.py +1 -4
  25. gns3server/utils/images.py +17 -4
  26. gns3server/version.py +2 -2
  27. gns3server/static/web-ui/main.e55eeff5c0ba1cf4.js +0 -1
  28. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/LICENSE +0 -0
  29. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/entry_points.txt +0 -0
  30. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/top_level.txt +0 -0
gns3server/server.py CHANGED
@@ -23,7 +23,6 @@ Start the program. Use main.py to load it.
23
23
  import os
24
24
  import datetime
25
25
  import locale
26
- import argparse
27
26
  import psutil
28
27
  import sys
29
28
  import asyncio
@@ -33,13 +32,10 @@ import uvicorn
33
32
  import secrets
34
33
  import string
35
34
 
36
- from gns3server.controller import Controller
37
- from gns3server.compute.port_manager import PortManager
38
35
  from gns3server.logger import init_logger
39
36
  from gns3server.version import __version__
40
37
  from gns3server.config import Config
41
38
  from gns3server.crash_report import CrashReport
42
- from gns3server.api.server import app
43
39
  from pydantic import ValidationError, SecretStr
44
40
 
45
41
  import logging
@@ -90,40 +86,13 @@ class Server:
90
86
  else:
91
87
  log.info(f"Current locale is {language}.{encoding}")
92
88
 
93
- def _parse_arguments(self, argv):
89
+ def _setup_logging(self, args):
94
90
  """
95
- Parse command line arguments and override local configuration
91
+ Setup logging.
96
92
 
97
- :params args: Array of command line arguments
93
+ :param args: command line arguments
98
94
  """
99
95
 
100
- parser = argparse.ArgumentParser(description=f"GNS3 server version {__version__}")
101
- parser.add_argument("-v", "--version", help="show the version", action="version", version=__version__)
102
- parser.add_argument("--host", help="run on the given host/IP address")
103
- parser.add_argument("--port", help="run on the given port", type=int)
104
- parser.add_argument("--ssl", action="store_true", help="run in SSL mode")
105
- parser.add_argument("--config", help="Configuration file")
106
- parser.add_argument("--certfile", help="SSL cert file")
107
- parser.add_argument("--certkey", help="SSL key file")
108
- parser.add_argument("-L", "--local", action="store_true", help="local mode (allows some insecure operations)")
109
- parser.add_argument(
110
- "-A", "--allow", action="store_true", help="allow remote connections to local console ports"
111
- )
112
- parser.add_argument("-q", "--quiet", default=False, action="store_true", help="do not show logs on stdout")
113
- parser.add_argument("-d", "--debug", default=False, action="store_true", help="show debug logs")
114
- parser.add_argument("--logfile", "--log", help="send output to logfile instead of console")
115
- parser.add_argument("--logmaxsize", default=10000000, help="maximum logfile size in bytes (default is 10MB)")
116
- parser.add_argument(
117
- "--logbackupcount", default=10, help="number of historical log files to keep (default is 10)"
118
- )
119
- parser.add_argument(
120
- "--logcompression", default=False, action="store_true", help="compress inactive (historical) logs"
121
- )
122
- parser.add_argument("--daemon", action="store_true", help="start as a daemon")
123
- parser.add_argument("--pid", help="store process pid")
124
- parser.add_argument("--profile", help="Settings profile (blank will use default settings files)")
125
-
126
- args = parser.parse_args(argv)
127
96
  level = logging.INFO
128
97
  if args.debug:
129
98
  level = logging.DEBUG
@@ -137,6 +106,15 @@ class Server:
137
106
  quiet=args.quiet,
138
107
  )
139
108
 
109
+ @staticmethod
110
+ def _load_config_and_set_defaults(parser, args, argv=None):
111
+ """
112
+ Parse command line arguments and override local configuration
113
+
114
+ :param parser: ArgumentParser instance
115
+ :param args: command line arguments
116
+ """
117
+
140
118
  try:
141
119
  if args.config:
142
120
  Config.instance(files=[args.config], profile=args.profile)
@@ -157,7 +135,10 @@ class Server:
157
135
  }
158
136
 
159
137
  parser.set_defaults(**defaults)
160
- return parser.parse_args(argv)
138
+ if argv is None:
139
+ argv = sys.argv[1:]
140
+ args = parser.parse_args(argv)
141
+ return args
161
142
 
162
143
  @staticmethod
163
144
  def _set_config_defaults_from_command_line(args):
@@ -174,6 +155,8 @@ class Server:
174
155
  config.Server.enable_ssl = args.ssl
175
156
 
176
157
  def _signal_handling(self):
158
+
159
+ from gns3server.controller import Controller
177
160
  def signal_handler(signame, *args):
178
161
 
179
162
  try:
@@ -239,9 +222,10 @@ class Server:
239
222
  log.critical("Can't write pid file %s: %s", path, str(e))
240
223
  sys.exit(1)
241
224
 
242
- async def run(self):
225
+ async def run(self, parser, args):
243
226
 
244
- args = self._parse_arguments(sys.argv[1:])
227
+ self._setup_logging(args)
228
+ args = self._load_config_and_set_defaults(parser, args)
245
229
 
246
230
  if args.pid:
247
231
  self._pid_lock(args.pid)
@@ -256,7 +240,6 @@ class Server:
256
240
 
257
241
  self._set_config_defaults_from_command_line(args)
258
242
  config = Config.instance().settings
259
-
260
243
  if not config.Server.compute_password.get_secret_value():
261
244
  alphabet = string.ascii_letters + string.digits + string.punctuation
262
245
  generated_password = ''.join(secrets.choice(alphabet) for _ in range(16))
@@ -267,9 +250,9 @@ class Server:
267
250
  else:
268
251
  log.info(f"Compute authentication is enabled with username '{config.Server.compute_username}'")
269
252
 
270
- # we only support Python 3 version >= 3.8
271
- if sys.version_info < (3, 8, 0):
272
- raise SystemExit("Python 3.8 or higher is required")
253
+ # we only support Python 3 version >= 3.9
254
+ if sys.version_info < (3, 9, 0):
255
+ raise SystemExit("Python 3.9 or higher is required")
273
256
 
274
257
  log.info(
275
258
  "Running with Python {major}.{minor}.{micro} and has PID {pid}".format(
@@ -297,11 +280,13 @@ class Server:
297
280
  host = config.Server.host
298
281
  port = config.Server.port
299
282
 
283
+ from gns3server.compute.port_manager import PortManager
300
284
  PortManager.instance().console_host = host
301
285
  self._signal_handling()
302
286
 
303
287
  try:
304
288
  log.info(f"Starting server on {host}:{port}")
289
+ from gns3server.api.server import app
305
290
 
306
291
  # only show uvicorn access logs in debug mode
307
292
  access_log = False
@@ -14,8 +14,9 @@
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
-
18
- from jose import JWTError, jwt
17
+ from joserfc import jwt
18
+ from joserfc.jwk import OctKey
19
+ from joserfc.errors import JoseError
19
20
  from datetime import datetime, timedelta, timezone
20
21
  import bcrypt
21
22
 
@@ -56,7 +57,8 @@ class AuthService:
56
57
  secret_key = DEFAULT_JWT_SECRET_KEY
57
58
  log.error("A JWT secret key must be configured to secure the server, using an unsecured default key!")
58
59
  algorithm = Config.instance().settings.Controller.jwt_algorithm
59
- encoded_jwt = jwt.encode(to_encode, secret_key, algorithm=algorithm)
60
+ key = OctKey.import_key(secret_key)
61
+ encoded_jwt = jwt.encode({"alg": algorithm}, to_encode, key)
60
62
  return encoded_jwt
61
63
 
62
64
  def get_username_from_token(self, token: str, secret_key: str = None) -> Optional[str]:
@@ -73,11 +75,12 @@ class AuthService:
73
75
  secret_key = DEFAULT_JWT_SECRET_KEY
74
76
  log.error("A JWT secret key must be configured to secure the server, using an unsecured default key!")
75
77
  algorithm = Config.instance().settings.Controller.jwt_algorithm
76
- payload = jwt.decode(token, secret_key, algorithms=[algorithm])
77
- username: str = payload.get("sub")
78
+ key = OctKey.import_key(secret_key)
79
+ payload = jwt.decode(token, key, algorithms=[algorithm])
80
+ username: str = payload.claims.get("sub")
78
81
  if username is None:
79
82
  raise credentials_exception
80
83
  token_data = TokenData(username=username)
81
- except (JWTError, ValidationError):
84
+ except (JoseError, ValidationError, ValueError):
82
85
  raise credentials_exception
83
86
  return token_data.username
@@ -46,6 +46,6 @@
46
46
 
47
47
  gtag('config', 'G-0BT7QQV1W1');
48
48
  </script>
49
- <script src="runtime.24fa95b7061d7056.js" type="module"></script><script src="polyfills.319c79dd175e50d0.js" type="module"></script><script src="main.e55eeff5c0ba1cf4.js" type="module"></script>
49
+ <script src="runtime.24fa95b7061d7056.js" type="module"></script><script src="polyfills.319c79dd175e50d0.js" type="module"></script><script src="main.2e807eb4bc32f838.js" type="module"></script>
50
50
 
51
51
  </body></html>