Repository navigation
Replies: 1 comment 4 replies
|
Thanks for the detailed analysis 👍 I had a quick read and option 3 would probably be the most suitable however I really need to think about the best long term solution. |
4 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I'm raising this as a discussion rather than an issue for now, to get some feedback on the best approach to go forward.
Recent changes in 2.2.61 to symlink validation have affected me, but to avoid this being an XY problem, let me outline my actual use case first, before moving onto how symlinks come into it.
At the moment, exporting a portable project either includes all base images, or none. But I need to do this selectively:
That's the first part. The second part is that I'm running gns3 in containers; I want them to be able to have read-write access to their own local
images_dirso that I can import a project which has project-specific images, but also to have access to a common pool of shared images. This is a separate directory which I mount read-only in each container, so they can't mess with it and I don't have to worry about concurrent updates.What I've been doing up to now is to replace the large shared images with symlinks pointing to an absolute target. Then the project export contains only symlinks for those files, whilst still containing the project-specific base images in full.
Here's an example of such a project:
What unzip -v doesn't show is which are symlinks. If I unzip this bundle:
Now you can see them. The shared items are symlinks to a well-known, trusted directory. When the project is imported, if you don't already have (say) the image
nsrc-rs-20230306-de889aa8.qcow2in your<images_dir>then the import creates a symlink from<images_dir>/QEMU/nsrc-rs-20230306-de889aa8.qcow2(which is where gns3 looks for the image) to/vtp/shared/images/QEMU/nsrc-rs-20230306-de889aa8.qcow2(which is where you keep your manually-managed images); it's up to you to fetch the image there if you don't already have it.It's working fine.
The problem
2.2.61 changes this, because project import now enforces the following rules:
images_dir. This means that a relative symlink, which was initially unpacked under (say)/var/lib/GNS3/projects/XXXXX/images/QEMU/fooand validated to point relatively to somewhere under/var/lib/GNS3/projects/XXXXX/will get moved to (say)/var/lib/GNS3/images/QEMU/foowhere it could point relatively somewhere else.Anyway, I have to rethink how to handle my use case, and here are some ideas I have had.
Option 1: cross fingers
It might just work as-is, if I symlink
images/QEMU/footo../../shared/foo. It just so happens that because the file gets unpacked under<project-dir>/images/QEMUthen a relative symlink is allowed to point 1 or 2 levels up in the hierarchy - it is validated to remain within the project directory. Then, when it gets moved to the final target directory (say/var/lib/GNS3/images/QEMU) it will be allowed to point 1 or 2 levels up here, and I can mount a shared directory on/var/lib/GNS3/sharedand the symlink will point to it.This to me seems like an accidental behaviour of the new validation code, and I don't want to rely on it going forward. That is, you might change the validation in future so that image symlinks can only point within the
<images_dir>.It would be more likely to keep working if I mount the directory containing symlink targets as a subdirectory of
images_dir, e.g./var/lib/GNS3/images/shared. Thenimages/QEMU/foocan symlink to../shared/fooor../shared/QEMU/foo, without escaping/var/lib/GNS3/images.Option 2: limited support for absolute symlinks
For example, absolute symlinks could be allowed if they point within a "trusted" symlink directory (configurable by the user).
Aside: I note that there's actually another place where absolute file paths exist in imported projects: that's in qcow2 files that point to an underlying backing file.
This is especially relevant in snapshots. If absolute symlinks are a concern, then these files might also be a concern (and it also hinders portability of portable projects)
Option 3: specific support for
imagessymlinksThere could be specific support for symlinks which are under the
imagesdirectory. At the moment, all symlinks are validated the same way (under the project directory), and then_import_imagesmoves items into the shared images path (treating files and symlinks identically). If you add specific logic for symlinks under theimagesdirectory then this would be explicitly supporting my use case, which of course I would welcome.However, I haven't thought through exactly what form that support would be; again, it might be that image symlinks can point to a
trusteddirectory, instead of being validated to point within the project.Option 4: image exportable flag
It would be possible to mark individual images as "exportable" or "not exportable". The "not exportable" ones are simply skipped from the project export; it's the user's responsibility to populate them into the image store. This is basically the same as "exclude base images", but more selective.
At the moment, you could say I'm effectively marking an image as "not exportable" by replacing it with a symlink under
<images_dir>to some other directory. But there could be an explicit list of non-exportable images; or it could be a flag file, e.g.That solves the project export case. Project import of course does not have the image, and the user fixes it up as required: either installing the image, or a symlink in the images directory.
In my case, I could provide users with a supporting script to add symlinks pointing to the shared images directory; the project file is easy to parse with
jq.Option 5: multiple images directories
Instead of a single
<images-dir>, GNS3 could have a search path for images directories when it wants to open an image.This means I could put my shared images directory second in the path. And also, project export with "include base images" selected could only include base images which are in the first directory.
This solves the problem of separating "exportable" and "non-exportable" images, and of having a shared image repository, without needing any symlinks.
This could be quite a substantial change to GNS3 though? Or maybe not.
Option 5a: project-specific images directories
When thinking about option 5, I realised that if you're going to search for images across multiple directories, then you could have project-specific images.
What I mean is, you could use
<project-dir>/images/not just as a temporary staging area when importing a project, but just leave the images there. When running a project, you'd search for images there before looking in the main images directory, which becomes the images that are shared between projects.A project export could then include either:
A project import would only import images into the project's own images directory (get rid of the
_import_imagesentirely). If you want to promote any images to being shared, you'd move them by hand to<images-dir>.A side benefit is that projects could have different images (i.e. different md5sum) with the same name, without conflicting.
Other options?
I did wonder about turning the images directory into a blob store, where the filenames are the md5sums. Then you don't worry about symlinks at all, and you don't worry about name clashes any more; it's only the md5 that matters (or sha256 if you want to be more secure).
But that's a very major change to GNS3. Furthermore, you'd still need a way to differentiate between exportable and non-exportable images, and I'd still need to merge a writeable blob store with a read-only blob store, and it could become hard to track over time which images you want to keep and destroy, and where they came from. So I think this in itself doesn't solve my use case.
Sorry for the long ramble. I hope what I'm trying to do makes sense! And thank you for all the ongoing work you're doing with GNS3!
All reactions