-
-
Notifications
You must be signed in to change notification settings - Fork 160
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
feature: implement device access and new security spec #620
Conversation
Great idea! How would you handle the metadata info for the requesting device? |
Not sure exactly what your asking, but I have an open PR in the spec for meta data : SignalK/specification#454 And a PR on node server: #481 Is this the "metadata info" you are referring to? |
yes exactly, with the meta delta a new device could populate some of the meta after approval. |
What if the initial connection request had a way to include more info about the requester? Now there is just one string, how about including something like meta deltas? |
Yes this would help. We should be aware that some devices can have limitations to handle long Strings. |
Yep, meta deltas will be available for all devices. |
What kind of sensors/devices are you imagining? All IP connected? |
Not sure I understand what the user case is here for meta data. Can you give me an example of what a device would supply? |
@zubenubi yes, this is for IP connected devices. Really could be any kind of device, like a display, engine sensors, wind sensors, etc. Clients could even use this. So for example, when your buddy gets on your boat, he can open WilhelmSK, it makes an access request, you get a notification on your phone and go give him read-only permission. No need to create a userid/password and then have to type it in the app. |
90c5b29
to
b1c1c1a
Compare
@sbender9 Is this intended to replace the current CLI approach of getting a Security Token with signalk-generate-token? Want to make sure I understand the purpose. |
Yes, this removes the need to manually create the token and configure it on the device. The script won't go away, so it can still be done the old way. |
Excellent! That's what I was hoping. Thanks. |
Looks good, I like this kind of approach. Some thoughts:
|
|
@sbender9 you'r right, I can't think of one. I guess I was thinking of proper "cleanup", on shutdown or retry, but why bother? It could just do a new request after startup and let server bother with the invalidation of the "old" request. If that expiry is implemented, it's never a problem. How does the notification -> reply work? I.e. the notification is just a delta message (I assume), which disappears from the tree after the request has been granted, denied or has expired? The reply is just a HTTP request from a client? |
@fabdrol The client gets a uuid in the response when make the access request. It then polls via REST using that uuid to get the response. |
I agree we need this functionality but all data needs to be in a signalk message, rather than depending on the url for context, eg
The reason is simple, how do I make an access request (using a url) if I have a device on some other form of connection (serial, MQTT, STOMP, COAP)? We need to ensure everything in signalk can be done without depending/assuming http/url/webbrowser |
@rob42 I agree that we need to support other transports, but I think for a REST interface, it should look like normal REST calls. You would not have "accessRequest", in the REST interface. Would you agree? I think I'll go ahead and do a WS implementation of this. In that case I would do as you said, and then that could be used for other transports as well. |
Agreed, the REST interface already 'knows' the context of the data. This is also consistent with the other REST interfaces, when we GET .../navigation/position it just returns the lat/lon object, not the full tree. In the artemis-server case the REST interface is a facade for the signalk message, it would just construct the full message and send into the signalk server anyway, and await and return the response. |
It would be good to align the message format with the current norm for updates/GET/PUT/LIST messages I think we should have more tags at the
|
@rob42 I've added a section on doing this via WS, can you review? |
I had a look but Im not familiar with the code or the libs used so I cant make much of it Im afraid. Sorry I dont have the time to study up on them at the moment. We really need to make a schema change to allow a set of new keys to the delta format to allow this and other tasks but I'm buried next few days |
I just want you to look the at the ws messages. I can do a PR to the spec once this is ironed out. |
sorry for being dense, I cant see any ws samples? |
It's in the PR description above, search for "Requests can also be made via web sock or other protocols" |
When using stateless async messaging (eg ws, MQTT, etc) there is no way for the client to correlate a reply message to a previously sent request unless the messaging system uses a correlation id. For our case the best solution is to add a generated uuid to the message, since that avoids having to work with different correlation systems on different transports. Hence the reply will have to have an identifier from the request. If that is In the example above its not clear (due to formatting) that the issued token should be inside the
|
You might also add a WHITE_LIST, BLACK_LIST state so that devices dont keep asking every reboot, or rogue devices keep trying to get in. Dont really want notification DOS attack on the helm :-) |
What is the role of Device access not allowed is not a good example of an ERROR, as that should result in DENIED. The messages are not symmetric, request is If the client drops the ws connection before receiving confirmation how does it get the response if the request was granted/denied while it was not connected? What if the client never sees I updated the messages in the description to include the uuid for request-response collation. This makes the uuid a client issued request id instead of a client id, which was probably what Scott suggested originally. Is this the way it should be? In REST things are different, as the server issues the request id. I think it would be better to not use the name I think it would make sense to start working on this as a PR to specification in parallel with the implementation, if for nothing else than gaining Github versioning and diffing for the spec addition. Appendix or a new chapter? Lest the specification never happens... BTW I would be happy with just getting this defined for REST, ws adds quite a bit of complication in spec and implementation. |
The current delta format needs extension to include at least We could add an |
0293174
to
43c7021
Compare
ea74d32
to
d85eccd
Compare
When giving permissions to a device the optimal way to do it is to provide RW based on keys, and using wildcards, just as we do via subscribe etc. So a device will request READ for a list of keys, and WRITE for another list. Bit like android permissions, you can grant/deny each. Probably there would be defined 'profiles' to save a lot of detail, eg I think we should do the definition of that later (a lot of work), after the basics are settled, but the design should be compatible with that concept. |
registerActionHandler remains for backwards compatability
TODO:
This PR provides a way for devices to request an access token from the server.
It also has changes to conform to the new request/response and security specifications.
The device will send a REST request to the server:
curl -k --header "Content-Type: application/json" --request POST --data '{"clientId":"1234-45653-343453","description": "My Awesome Sensor"}' https://localhost:3443/access/requests
The server will return a json response with a request identifier:
{"requestId":"60240a45-bbcb-46f0-8df6-c7a3e048bec0"}
A Signal K notification is sent out when this happens and In the admin ui, there is a list of devices that are requesting access:
In the mean time, a device should poll the server using the requestId in the response above to see if it has been granted access and get the token:
The request is pending:
The request is denied:
The request was approved:
On approval, the device would save the token in a secure way and use it when sending or requesting data. Subsequently, when a device gets an 'Access Denied' response, it should send a new request for access to get a new token.
In the same vane, this PR also provides a way for users to request access to the server.
The login page now shows a "Sign Up" link:
The user will then be presented with a page to enter an email address and password:
A notification is sent out when this happens and In the admin ui, there is a list of users that are requesting access:
Example of a client that could allow users to easily approve requests: