Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request] Create a more granular permission system #1110

Closed
foosel opened this issue Nov 6, 2015 · 30 comments
Closed

[Request] Create a more granular permission system #1110

foosel opened this issue Nov 6, 2015 · 30 comments
Labels
difficult done Done but not yet released request Feature request
Milestone

Comments

@foosel
Copy link
Member

foosel commented Nov 6, 2015

At the moment OctoPrint only distinguishes between three user roles if ACLs are enabled:

  • Guests/Anonymous: May view the current status, including progress, file being printed, gcode preview, webcam, terminal output. May also download timelapses and uploaded files.
  • Users: All of the above, plus may control the printer, upload files, start/pause/cancel jobs, send commands to the printer.
  • Admin: All of the above, plus can view and manage settiings, update the installation, install plugins.

As various tickets (e.g. #950, #1109 and #640 to name a view) and posts on mailinglist etc have shown, that is not granular enough for many usage scenarios.

Instead there should be a more granular permission system that allows:

  • giving or revoking access to individual functionality per user group (that means both in the UI and on the API endpoints)
  • possibly allowing adding custom user groups for more complex usage scenarios

In order to do this we need to

  • model user groups vs. permissions on a per-feature-level (roles)
    • determine which roles need to be recognized for vanilla OctoPrint and model them
    • add a way for plugins to define individual roles that can be offered for the user to attach to groups
  • create some way to store user groups vs. associated permissions (currently that stuff is hard coded)
  • add a permission editor
  • document permissions in API documentation ("needs user group with role X")
  • clearly communicate the limits of the permissions in the interface - we cannot prevent people from viewing the webcam if the URL is known since access to the webcam is provided by the webcam server, OctoPrint merely embeds it, so it cannot control access to it, that needs to be done by the webcam server
  • Not only protect the existing API endpoints this way, but also the static endpoints as served by Tornado (e.g. timelapse and printable downloads)
@foosel
Copy link
Member Author

foosel commented Nov 6, 2015

Documentation of Flask Principal: https://pythonhosted.org/Flask-Principal/

@UM2EXTENDED
Copy link

This would be a very useful improvement.

For beginner users it will be necessary to print files without the risk of damaging the printer by using the movement controls or the Terminal. Simple guest users don't provide this.

Especially for third parties this will be the minimum security requirement.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

Fun fact: movement controls are disabled while printing for that exact reason.

@UM2EXTENDED
Copy link

Sure I know while printing it's off, but not before and after.

In my case I granted access to a beginner user and he watched the printer head moving trough the camera (top view position), but he didn't noticed the heater bed was at Z0 and he moved it down (up arrow) several times. Now the Z motor is damaged and need to be replaced on UM2 Extended.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

That on the other hand is something your firmware shouldn't even allow you to do (move past end stop).

@UM2EXTENDED
Copy link

Strange, as the standard marlin firmware 15.04.2 is installed on this UM2 Extended. Also with the printer itself I can't lower the heater bed to much, it stops automatically. But with Octoprint control buttons it's possible all the time to lower it even on end stop position.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

OctoPrint only send regular move commands, nothing special, same stuff that is in your sliced files. So if it's possible in your printer's firmware to move past the end stops with a simple G0, you don't need to OctoPrint to "achieve" that.

Now I might be mistaken, but I seem to remember that at least my ultimaker classic and definitely my printrbot refuse to move steppers past any end stops. Which would be the sane thing to do too.

@nophead
Copy link
Contributor

nophead commented Nov 9, 2015

The difference is jog buttons use relative mode whereas gcode files are absolute moves, so it is possibly a firmware bug. Or perhaps the axis had not been homed.

Very odd to damage a motor. Stepper motors don't mind being stalled.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

Apparently UM2 firmware by default disables any end stop checks unless homing and relies on software end stops instead. Make of that what you will. Easily fixed by recompiling the firmware.

See: https://ultimaker.com/en/community/view/8373-printing-over-serial-um2-does-not-respect-end-stop-switches-limits

@nophead
Copy link
Contributor

nophead commented Nov 9, 2015

Yes but that is normal and soft limits should prevent it going below zero after it has homed.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

That may well be (although I'd not consider disabled end stops normal personally but ymmv), but even if you have not homed the soft limits should prevent you from moving to a lower coordinate than from where you started (zero being assumed then to be the initial position on boot). So either the firmware there indeed has some serious bug or the printer in question is started up with the head inside the bed.

In any case, nothing that OctoPrint can solve or which actually belongs into this ticket, so I suggest to take further discussions of that topic to the mailing list (if necessary) :)

@nophead
Copy link
Contributor

nophead commented Nov 9, 2015

Actually the bed moves, not the head on UM2, so if it it was moving down, that is away from Z0 towards Z MAX. That direction is allowed before homing. A better firmware would enable the limits until it had homed, rather than just during homing.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

should prevent you from moving to a lower coordinate

;)

@nophead
Copy link
Contributor

nophead commented Nov 9, 2015

Yes but a lower Z coordinate is bed moving upwards. The reported crash is the bed moving downwards, which is a higher coordinate.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

Considering that the bed was at Z0 (head right next to bed, or am I misinformed here and th is can also mean Zmax?) and the user didn't notice that when moving it, I assumed that the mentioned up arrow was with inverted z axis configured in OctoPrint and hence negative z direction (which makes sense for a UM) and the user moved the bed against the head repeatedly. Otherwise I'm unclear why the initial position of Z0 would even be of relevance for that tale.

Maybe @UM2EXTENDED wants to shed some light on this to solve this mystery of what really happened, because I'm sure confused now.

@UM2EXTENDED
Copy link

OK, here comes the bright light for the almighty darkness :-)

I have printed a file created with Cura and RepRap gcode settings by using Octoprint.

Cura start.gcode
;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M109 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M82 ;set extruder to absolute mode
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G0 X20 Y20 F{travel_speed} ;bring extruder to the front
G1 Z25.0 F{travel_speed} ;move the platform down 25mm
G92 E0 ;zero the extruded length
G1 F200 E20 ;extrude 20mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...

Cura end.gcode
;End GCode
M107 ;fans off
M104 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G21 ;metric values
G90 ;absolute positioning
G28 Z0 X0 Y0 ;move Z and X/Y to min endstops
G91 ;relative positioning
G1 E-5 F300 ;retract the filament
M84 ;steppers off
G90 ;absolute positioning
;{profile_string}

After this the beginner user connected to octoprint and started to control the printer by using the arrow buttons in control tab. He pressed the up arrow several times which causes lowering the build plate right into the basement.

@foosel
Copy link
Member Author

foosel commented Nov 9, 2015

Ok, @nophead you were right then, sorry :D

Impressive though, traveling the full z length with video feedback and not noticing that this might be bad O.o

@nophead
Copy link
Contributor

nophead commented Nov 9, 2015

I expect the bed moves out of the view of the camera at the bottom, just as the nozzle moves out of range of mine at the top.

I have actually done the same thing. I moved Z upwards remotely and had forgotten to home it so it smashed into the endstop. Didn't damage anything but it did move the endstop requiring calibration.

@foulowl
Copy link

foulowl commented Nov 28, 2015

Just wanted to say that I think this is a fantastic idea. Thank you to everyone for your work on this issue.

@JosvdP
Copy link

JosvdP commented Jan 19, 2016

I'd love this feature.

@ntoff
Copy link
Contributor

ntoff commented Feb 7, 2016

I have actually done the same thing. I moved Z upwards remotely and had forgotten to home it so it smashed into the endstop. Didn't damage anything but it did move the endstop requiring calibration.

A few incidences like this on mine lead me to enable end stops permanently (not just homing) and to also add max end stops for all the axes. I can smash that move button as much as I like even without homing and it'll stop once it gets to an end stop at either end of any axis.

@javawizard
Copy link

@foosel, have you (or anyone else) started on this? I might take a crack at a PR if not.

@oschonrock
Copy link

oschonrock commented Mar 3, 2017

My motivation was simply: Make my Octopi secure.

Not because I want to port-forward the internet onto it (although that would make it critical), but just because it is best practice as far as I am concerned. I also don't let anyone on my network just read the content on my XMBC RPi or get to the pages on my router without authenticating themselves. On my Octopi I mainly didn't want webcam images of my printer room flying around my network without any auth on them, but the same goes for much of the other content on the octoprint UI.

I understand that it is non-trivial to secure the Octoprint installation as this was not part of the original architecture. The best suggested, simple method is http-basic-auth on haproxy. I thought it might be useful to document right here in this github-issue how to do that, having spent a couple of hours fiddling with the options, so here is my relevant haproxy.cfg section:

...
userlist OctopiUsers
        # it's nice if list of users matches those from octoprint's db                                                                                                                    
        # generate these with following command on ubuntu 16.04 or on the pi after apt-get install whois (which includes mkpasswd)                                                    
        # echo "somesecret" | mkpasswd --method=sha-512 -s                                                                                                                            
        user admin password $6$sxqXPbDrVAP$Tl9K8oPh9/BZ2c2IQCgl7.XFraH33P1MTiMbMJLrrYZTYXUmF7FyvqOWnp9L.6Z5uL0SsXSNm8MLD0zTLPZXq0
        user user1 password $6$bBIw2tlfVE$pSws2Gee6DHaGsMRqgVPTo8MLb2RfI3udohi6/YKPLi.et4lFyBdqGmrLMyvDbGK58j9zESU5PqpGJbL5SBqJ1
        user user2 password $6$st1qrF94Fv$LYj5HWIPBB8LpTqlApnSKu.U00YCj457TdlIKXYYts/bx.Ztb.4zAnG20GCblv4Aj18sooKW2iot8CnEriQ6V0

frontend public
        # don't serve unencrypted on port 80, ssl only (also because basic auth below)                                                                                                
        # bind *:80                                                                                                                                                                   
        bind 0.0.0.0:443 ssl crt /etc/ssl/yourdomain.com.chained.pem

        # protect entire site with http basic auth, because octoprint shows far too much without auth                                                                                 
        acl AuthOkay_OctopiUsers http_auth(OctopiUsers)
        http-request auth realm OctoPrintAccessControl if !AuthOkay_OctopiUsers
....

Note that I have disabled port 80 altogether. As Snowden might agree, unencrypted http over port 80 is basically deprecated, especially if you are using http-basic-auth which sends the password in plain text. It's not that hard to type "https://".

Note that I am using my own SSL cert, to avoid those security warnings, ie proper trusted SSL.

There are some notes in there about how to produce the crypt(3)'ed password strings.

Hope this helps someone, until Gina comes up with something much better.

Keep up the great work Gina. Everyone else should support her financially.

@foofoodog
Copy link

I am not seeing this needs to be built into the core system. As others have mentioned maybe some sort LDAP integration plug point is required, with maybe some default sort of YAML based one provided by default. The issue is when you get into some kind of role based security taxonomy, every other person will want to do it differently, and so there are no macro groups by default that everyone can agree upon. Every single method will have to have a distinct @authorize attribute if you will, and then there would need to be a UI that maps those distinct privileges to admin defined groups. This is reinventing group policy, and if you ever worked with that, it is a full-time job for some poor soul. Maybe @foosel can come up with a more clever solution than I can even imagine to plug this in without polluting the code base with IsAllowed wrappers for some atomic granular security mechanism that 99% of people will never use. And so there is the challenge :) And I love cookies, still.

@foosel
Copy link
Member Author

foosel commented Oct 9, 2017

@Salandora I took the liberty to assign this to you since it's you who's been working on this for a while now.

@HongkaiWuLab
Copy link

Is it difficult changing the login to a splash screen instead of the top right corner (something similar to NanoDLP)? The ideas above are good (improved permissions management) but it sounds difficult to implement and requires more discussion. If there is a simple method maybe that is the best place to start and then improve on it with future upgrades.

@foosel
Copy link
Member Author

foosel commented Oct 17, 2017

@HongkaiWuLab It's not difficult enforcing a login screen instead of the usual web interface if no login session is detected (and I even wrote a proof of concept plugin for that a long time ago), but that's equivalent to taping a sticker to your unlocked car that says "locked". If the underlying API still allows anonymous access to the printer status or download of the file, putting a scary login dialog in front of things doesn't help. That's merely simulating security.

The API needs to enforce more restrictive permissions, and there's no easy and fast way to do this properly. If you need a solution now, look into further protection one layer above OctoPrint (read: something like HTTP BasicAuth done by the reverse proxy in front of it).

@foosel
Copy link
Member Author

foosel commented May 25, 2018

#2198 has been merged, this will be part of 1.4.0 (no timeline yet, other large stuff that needs to go in there still needs to be done)

@foosel
Copy link
Member Author

foosel commented Mar 4, 2020

1.4.0 has been released.

@foosel foosel closed this as completed Mar 4, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
difficult done Done but not yet released request Feature request
Projects
None yet
Development

No branches or pull requests