Neos-Metaverse / NeosPublic

A public issue/wiki only repository for the NeosVR project
195 stars 9 forks source link

Feature Request: Write / Read Text Files with LogiX #334

Open ProbablePrime opened 4 years ago

ProbablePrime commented 4 years ago

As i've been hanging out at the SHFR Lab and looking at how they're using Neos for research and something that keeps coming up is how students and researchers get their results out of Neos.

The goal for their Neos Experiments, is to make an experiment as seamless as possible and for it to not require developer based tooling or for someone such as Hamish or Myself to export data on behalf of these research students. Some students have unfortunately switched to using Unity or other VR platforms for their research where file writing is allowed.

The best option here is to allow file writing in some fashion from Logix.

I believe that Hamish has asked for this before but I wanted to open a GH issue to document and discuss feedback and issues etc. To get us started I wanted to list out some of the suggestions and feedback which Hamish was talking to me about.

Using a Plugin

Historically SHFR has been given a plugin written by outsider but the management, distribution and maintenance of said plugin is not ideal. Everytime Neos changes the plugin has to be updated and re-deployed to the lab. There are lots of machines here in the lab and there are other Neos units within the field that might not even be aware that an update is required.

Using Server Based Logging

It was also suggested to try to use the GET node to log data but this also isn't ideal as this would require separate managed infrastructure that the research team will have to maintain.

Using text exports

Whilst this works the added step of grabbing the text and using the file browser unfortunately adds extra steps and problems that become unwieldy when multiple research subjects have to progress through an experience. Doing this say 100 times a day for your research becomes tiresome.

Additionally the data volumes here get very problematic as a big floating text plane needs to be within the world.

Security

There are security concerns here but i believe that the pattern used with the HTTP GET node are suitable. A node which requests access to a file or folder before writing/reading could be created that follows the logic of the request host access network node.

Additional restrictions for example on the size of the file that can be written could also tighten down possible risk.

Largely the researchers only require text files so restricting the types of files that can be written is ok.

Alternatives

Pipes would be a lovely alternative, pipeing data as a stream over to another app would allow for aggregation and logic to be performed. The students here are very familiar with LabView.

I understand this is a large and complex ask but wanted to make sure it was documented and available for discussion here on the issue tracker.

Thanks!

Frooxius commented 4 years ago

Hmm I'm not really sure about this at this point, at least not adding it quickly without proper security framework in place.

Using similar approach to HTTP GET might work, but I'm not 100 % confident with the security risks right now, as this gives direct write access to the computer itself. Perhaps if the user was prompted to create the file first?

Do they need to create all the files programmatically as well or is having manual request for the file ok (e.g. it would ask at the beginning of the experiment)

There's also issue with future compatibility. If I implement a quick solution now, we might later find out that it's not a good approach and needs to be scrapped, but if people already built frameworks on top of it all those would break, so I prefer to give this more care from the get go.

Could an alternative be simplification of the plugin distribution/loading? Why does the plugin have to be updated and re-deployed? Generally the assemblies should work for a while without changing them, unless there are breaking changes in the ABI.

ProbablePrime commented 4 years ago

Answering inline: Using similar approach to HTTP GET might work, but I'm not 100 % confident with the security risks right now, as this gives direct write access to the computer itself. Perhaps if the user was prompted to create the file first? Once per session asking might be ok, but not on each file write. Imagine 100 research subjects all requiring a manual step before the experiment can start.

Do they need to create all the files programmatically as well or is having manual request for the file ok (e.g. it would ask at the beginning of the experiment) Asking once at the start of a research session would be ok, but for each file would lead to a complicated handover between research subjects. Again imagine 100 people who have dedicated an afternoon to get in and out of Neos to collect data.

There's also issue with future compatibility. If I implement a quick solution now, we might later find out that it's not a good approach and needs to be scrapped, but if people already built frameworks on top of it all those would break, so I prefer to give this more care from the get go. I understand, if you are worried about the hackyness/fragility then please take your time.

Could an alternative be simplification of the plugin distribution/loading? Why does the plugin have to be updated and re-deployed? Generally the assemblies should work for a while without changing them, unless there are breaking changes in the ABI. I think the updates are a function of how long ago Outsider wrote the plugin. it would be possible to periodically update it and give to someone at the lab but once its there the problems start.

Delivering a plugin to 16 computers in the lab is quite problematic, once delivered and installed research users have to know to select the plugin to be loaded if they need it. If they dont and then accidentally load into a world that relies on that plugin then they run into issues.

Additionally it makes collaboration harder, Hamish can't enter worlds of users that don't have this plugin whilst it is enabled.

I hope the commentary helps, I get that this is hard.

What about Pipes? https://docs.microsoft.com/en-us/dotnet/standard/io/pipe-operations

Anomalous commented 4 years ago

If using pipes is an acceptable solution (meaning it's OK to have to run another program on the computer), why not have the other program listen for HTTP requests and connect to it with the GET node?

You mentioned LabView in specific. It looks like LabView has a Web Service component, so it should be pretty easy to talk directly to LabView using the GET node, right?

I agree file reading/writing would be handy once the security implications are sorted out, and the improved plugin distribution even more so; just thinking about solutions that are immediately available.

ProbablePrime commented 4 years ago

Thanks for the comments.

On pipes, Its the streaming part of pipes that interests me the pipe allows for streams of data to be processed as streams.

Back on the get node: The GET node, is a sequential operation that might not run at the data speed that we need due to overhead and the HTTP burden. We're talking 10hz over up to 30 minutes.

We could store and then send the data but there is a limit to the length of a get request as a GET request in traditional http is not meant for data submission, POST or PUT are used for those. Using a GET to submit data is really also a hack due to this.

The end goal is to run these experiments without a requirement of any additional infrastructure including Lab View and that's why the ultimate goal/ask is for writing text files.

In summary maintaining added infrastructure such as labview or a http server isn't an end goal and could lead to flakey unreliable experiments.

We could explore using pipes in the interim but ultimately writing a text file is what would allow for awesome experiments within Neos. The GET node is just not suitable.

MR-Alex42 commented 4 years ago

Would a HTTP POST node be an interim solution? I'm guessing that its rather quick to implement. Text files are universal however using something like https://www.integromat.com/en/ offers many powerful ways to process the data and easily integrate with other services.

Frooxius commented 4 years ago

Hmm if you only asked once per session, then it wouldn't be a good security solution. The HTTP GET node asks for every single endpoint, because each one is unrelated resource.

If you instead asked only once if the world can write files, then this would still pose a severe security risk, because you don't know who's doing the writing. E.g. you could have them approve once process to have write access, but then anyone can bring malicious script and write files that they shouldn't, so it's not a good solution for that.

An alternative would be to mark the whole session as unsafe and don't allow anyone else to join. Are those sessions usually private or LAN only? Is it ok if only host has the write access, so it would be the host starting the session as "unsafe", so only they can write data to disk, but none of the joined users can? That would mean that it's up to the host to determine who can join the session and use the dangerous nodes.

That way there could be class of "unsafe" nodes, but they could only be used by host in a session that's explicitly marked as "unsafe". But even then it still requires care, because potential exploits could try using them in the wrong context (e.g. session that's not marked as unsafe) or tricking an user into starting an unsafe session by accident and wreaking havoc on their computer.

I'm not sure about pipes. If you're running HTTP on localhost, there's not that bigger overhead, you should be able to handle 10 Hz. Integrating these is problematic as they're platform specific (e.g. wouldn't work correctly on Android or add extra complications) and there would need to be some good system to work with them, as LogiX currently doesn't work with streams. Adding that might be more work than just designing a proper solution for files.

TehTurk commented 4 years ago

Would some sort of User opt in be alright? Long as there is dialogs to start the session it Should be ok no? Similar to NCR donation or opening links.

Frooxius commented 4 years ago

@TehTurk That would need to be done for each file access, but like ProbablePrime has said, this is too problematic for their usecase as they have many files.

If it's a single dialog, then any subsequent script has access to any file, even if it's malicious.

ProbablePrime commented 4 years ago

Hey Froox,

Thanks for the comments on the Pipes, I agree. I was suggesting alternatives to form conversation an to try and get us away from HTTP.

I thought it might be handy to outline the desired outcome in terms of experiment execution:

From this we have a couple of clear factors:

Based on the above, yes only allowing the host to write files would be acceptable and only allowing for LAN users to connect would also be good. That's what most of the lab's worlds are set to at the moment.

If an unsafe session can only be used by LAN users the "tricking" of a user into starting an unsafe world doesn't seem that doable.

It feels like this strategy starts us on a path to getting there.

Frooxius commented 4 years ago

@ProbablePrime That's good info! If it's only ever used at LAN, then this makes it significantly simpler as it's a clear separator. I can make it so those nodes simply won't function if the session isn't LAN only.

There's still one potential issue and that's what forms will those nodes take. Designing a good LogiX API for file manipulation would take quite some time too. How important is compatibility for this? I could add some quicker ones marked as "Experimental" with the idea that they will eventually be gone, breaking existing applications.

It's something I want to avoid for general features and always have a way forward (e.g. auto-upgrade from old API), but it also slows down the process.

ProbablePrime commented 4 years ago

Thanks for getting back to me,

Hamish had some theoretical questions on LAN only nodes:

Mostly we're trying to work out how we can build an experience collaboratively but then lock it down to lan users when we're ready to do the actual experiments.

As for your question on the API, our needs are very simple at the moment:

We dont need file system parsing or reading or directory listings and a static folder location is fine. Something within the Neos Installation is fine by us. We'd just create a desktop shortcut to this folder.

Therefore for at least an experimental node I would say:

Write File

Inputs

Write - Impulse Contents - String Filename - String

Outputs

OnSuccess - impulse OnFailure - impulse

As a lot of research projects are transitory as in they run for a set period of time and then are complete, having an experimental but possibly removed at a later date node is ok provided we have some notice of its impending removal date.

Frooxius commented 4 years ago

Probably not swapping, it would have to be restarted for the nodes to work. They would still exist when it's public though. But to actually have them work you'd have to start the world again as "Unsafe" which would allow it to be LAN only.

If it could be swapped, this could open up exploits again, by having user tricked into starting a world, joining it when it's public and then swapping to LAN only, when the remote malicious actor is already there.

If it's ok that the node will be removed at some point then it could be added. I want to avoid people depending on it long term and having to support its existence for a long while. I might even have it hidden by default, so you'd have to toggle the category via inspector. I can add it in like that soon.

ProbablePrime commented 4 years ago

Spoke to Hamish, we'd be very grateful for this approach, just let us know when you plan on removing it in the future.

ProbablePrime commented 4 years ago

Hey @Frooxius , This is working fantastically for our research student, see the Edu-Science discord channel for some pictures of their setup.

We do unfortunately have one ask though. Getting the experiment open and running is a little difficult because the researcher has to find the world orb on the machine and remember to open it in unsafe mode.

Prior to unsafe mode's creation I had created a desktop shortcut with the appropriate flags(which you also fixed THANK YOU), to open the world directly which was super useful for this and other experiments.

Unfortunately this doesn't work allow world opening in unsafe mode, I gather that this may be by design as you're very rightly keen to prevent unwilling file writes but I feel that a suitable compromise might be an additional command line flag to force unsafe mode.

The reason behind this is that if a potentially malicious user already has access to make such a shortcut on a target machine than they've already gained access to the file system.

With this flag an experiment setup for a researcher would be beautiful and rival some Unity Based experiments I saw:

  1. Researcher comes to the lab on a session day
  2. Researcher double clicks on the desktop shortcut for their current experiment
  3. Neos boots, loads into the world and everything is ready
  4. Participants put on the headset and participate smoothly

Is there something we can do here?

Thank you!

Frooxius commented 4 years ago

Hmm doing it in a link is tricky, as that's something that's innocuous enough so the user doesn't think about clicking it.

How exactly are you launching Neos? One thing I could do is have a one time configuration file, which will whitelist which worlds can be started in unsafe mode automatically. It would have to be placed in the Neos installation or somewhere else in the system. Would that work?

ProbablePrime commented 4 years ago

Our link target contains ""C:\Program Files (x86)\Steam\steamapps\common\NeosVR\Neos.exe" -DontAutoOpenCloudHome -ForceLANOnly -Open "neosrec:///U-SHFR/R-<recordid>"

A config file sounds good. I apologize for the moving goal posts here, we're so close :)

Frooxius commented 4 years ago

Okay added this in 0.8.18.40558. You can now use -OpenUnsafe to open the record. You need to make Config.json and place it next to the Neos.exe and put all the ones you want to open into a whitelist like so:

{
    "unsafeModeWhiteList" : [
        "neosrec:///U-ID/R-World-Id",
        "neosrec:///U-ID/R-World-Id2",
        "neosrec:///U-ID/R-World-Id3"
    ]
}
shiftyscales commented 4 years ago

As noted above, this has been implemented in the form of the experimental Write Text To File node, and the Unsafe Mode session flag.

ProbablePrime commented 4 years ago

@shiftyscales This should remain open for the more long term solution. This current one is most likely going to be removed at some point.

shiftyscales commented 4 years ago

Fair enough. I had figured the initial needs of the issue had been addressed (even if the solution itself is a temporary one) and if it were to be removed, it would be because it has been replaced by such an implementation, @ProbablePrime.

We can keep it open if that is your wish, though.

ProbablePrime commented 4 years ago

This one, does email me :). If this node is ever removed I need to do a bunch of work :)