[Pki-devel] TPS REST interface design
Ade Lee
alee at redhat.com
Mon Jul 1 16:37:05 UTC 2013
On Fri, 2013-06-28 at 23:57 -0500, Endi Sukma Dewata wrote:
> On 6/28/2013 9:36 AM, Ade Lee wrote:
> >>> Or is your intention to send in something with an "action" parameter -
> >>> in which case, the correct operation is a POST?
> >>
> >> I use 'action' in the modify token operation because I couldn't find a
> >> better replacement for the 'question' parameter in the original
> >> op=do_token. Ideally it should be called 'status' but there's already
> >> another attribute with that name. Any suggestion? This 'action' should
> >> actually be returned by the GET operation too. I'll add it after we
> >> finalize the name.
> >
> > do_token?question=X is essentially an operation where you are attempting
> > to set the state of the token resource - for example, from "active" to
> > "lost". There is no need for an additional parameter.
>
> I added a Change Token State operation:
> http://pki.fedoraproject.org/wiki/TPS_REST_Interface#Change_Token_State
>
> As discussed, for now we'll call this parameter 'next state', which will
> update the status & reason depending on the current state of the token.
>
> >>> 3. Should we be worried about a XSS attack here for modifying the state
> >>> of the token? My guess is that we need to take advantage of the nonce
> >>> mechanism, in which case, token state modification will require two
> >>> steps.
> >>
> >> Yes, but similar to our discussion in the past, nonces or ETags can be
> >> added in a later phase without changing the interface. Since the
> >> modification is a PUT operation, and the request attributes are obtained
> >> using a GET operation done earlier, this is a two-step operation.
> >> Without the nonce or ETag the GET operation will be optional, and the
> >> client can construct the request from scratch. But later the PUT
> >> operation can require a nonce or ETag from a previous GET operation.
> >
> > OK, please put the nonce in the design. We dont want to forget it.
>
> I added two sections related to this:
> http://pki.fedoraproject.org/wiki/TPS_REST_Interface#Concurrency_Control
> http://pki.fedoraproject.org/wiki/TPS_REST_Interface#Vulnerabilities
>
> >>> 4. You should also note that we will be sending back BAD_REQUEST (401?)
> >>> when the token state transition is not permitted.
> >>
> >> That should fall under "Normal application errors will return HTTP 4xx
> >> return code." We can add more details as we implement it.
> >
> > Right, I'm just pointing this out because in this case, there is a state
> > machine which determines which operations are successful. From the
> > point of view of the API, doing a token transition is just an attempt to
> > set the state of the token differently, but unlike something simple like
> > just changing an attribute value, the operation is subject to the
> > results of a state machine.
>
> I noted that in the response of Change Token State:
> http://pki.fedoraproject.org/wiki/TPS_REST_Interface#Change_Token_State
>
> >>> 5. In the response to PUT /tokens/X, it is not necessary to return the
> >>> state of the token. Rather, you should return a URL pointer to the
> >>> newly modified resource. The same comment applies to the other PUT
> >>> operations as well.
> >>
> >> Since PUT operation in general doesn't create a new resource, and also
> >> the request is sent to the resource URL being modified, there is no need
> >> to return a new location because it will be identical. In this design
> >> the new location will only be returned on POST operations when adding a
> >> new resource, which in this case the new resource location will be
> >> different from the POST target (the resource collection).
> >>
> > Agreed. But in PUT /tokens/X, you return state information. This is
> > not necessary. You should probably return nothing - other than status.
>
> See explanation in #10.
>
> >>> 6. Same question about XSS for add/remove token/ add/remove user.
> >>
> >> Similarly, nonces or ETags can be added later. As described earlier,
> >> modifying users is a two-step process too with GET and PUT. Add and
> >> remove operations do not require the client to do any other operation,
> >> but it can be made so without changing the interface. The DELETE can
> >> require a GET, but I'm not sure what operation should be required before
> >> add.
> >>
> > Yeah - we need to think about ADD. Being able to add a privileged user
> > for example by XSS would be troubling.
>
> I think we're mixing up CSRF and XSS. Nonces will be useful to prevent
> CSRF. XSS can be prevented by encoding/escaping the values.
>
Thats correct. I was thinking about CSRF.
> If we implement a single-page Web UI (like IPA Web UI) the client can
> obtain a nonce during login, then the UI will keep the nonce in memory
> throughout the session and use it for all update requests including add
> (the nonce should really be called CSRF token). CSRF attack usually will
> open a new page, so it will not be able to know the nonce.
>
> If we implement a multi-page Web UI (like the current Dogtag UI), the
> add operation can be done in 2 steps. The first page will generate the
> nonce, then the second page will execute the operation.
>
> >>> 9. Is there a mapping between Profile and Profile Mapping operations and
> >>> the old operations? Please put that in so we can see whether we have
> >>> complete coverage. In particular, I do not see an operation to
> >>> approve/enable a profile. This is important because we have Common
> >>> Criteria requirements that two users are involved in the approval of a
> >>> profile. In our case, IIRC we implemented it such that an admin can
> >>> configure a profile but an agent must approve it.
> >>
> >> There should be, but they are not in the docs and I have not had a
> >> chance to test all possible operations in the UI. Once I get the TPS
> >> instance back running I'll continue this. But in general we can
> >> implement something similar to the cert requests:
> >>
> >> /tps/rest/profiles/{id}/approve (all approvers will use the same URL)
> >> /tps/rest/profiles/{id}/enable
> >>
> > Thats fine - lets make sure we get those operations in.
>
> I added the missing mappings. I also added a Change Profile State operation:
> http://pki.fedoraproject.org/wiki/TPS_REST_Interface#Change_Profile_State
>
The way this is written, it looks like you are just doing a POST to
the /tps/rest/profiles/<ProfileID> and passing in "action" as a
parameter. Thats not very RESTful at all.
I think we want:
/tps/rest/profiles/{id}/{action}
where {action} is approve etc. This is also consistent with how we have
done this for cert-requests etc. as well.
> >>> 10. In POST /tps/rest/profilemappings, you return the location of the
> >>> profile mappings as well as the contents of the profile mapping
> >>> resource. You should just return the location. In fact, its probably
> >>> better to just return locations in general. The client would then use
> >>> GET to fetch the details if needed. This comment applies to many of the
> >>> resources.
> >>
> >> In general I'd rather return the resource attributes in the POST
> >> response than requiring the client to do a separate GET later. This
> >> response acts as a receipt/acknowledgement for the add request, and it
> >> will return the actual attributes stored on the server before any other
> >> operation is done on it. This is rather important because sometimes a
> >> lazy UI won't do an extra GET because it assumes the attributes don't
> >> change, where in fact they could be normalized, ignored, or generated by
> >> the server. It also prevents a possible (although unlikely) attack that
> >> inserts an operation between the POST and GET.
> >
> > I guess you are suggesting the same for PUT requests as above.
> > I'm not sure whether this is vaid reasoning or not. Just because you
> > see what has been posted (or PUT) in the server does not mean that this
> > data has not been changed the next time the data is accessed.
>
> There's never any guarantee that the data we get (either from PUT, POST,
> or even GET) has not been changed when we submit it for another update
> operation. The advantage of returning the data in PUT/POST response is
> we're pushing the updated data to the client's feet.
>
> > If anything, returning this data encourages lazy clients.
>
> On the contrary, by returning the data in the PUT/POST response the
> client will have little reason not to use it. If the client has no
> intention to get the new data anyway (either from PUT/POST response or
> by doing another GET) there's nothing we can do about it. But if the
> client wants to get the new data, using PUT/POST response is a much
> cheaper option.
>
> Compare the following code:
>
> user = users.update(user);
>
> with this:
>
> users.update(user);
> user = users.get(user.getId());
>
> > The fact is
> > though that we will have to implement nonces and possibly etags, and so
> > GETs will become mandatory for any changes.
>
> Not necessarily. ETag is only an optimistic lock; it's not a guarantee
> that the data won't change. The PUT/POST response will also provide
> ETag. Also see comment #6, we may be able to reuse the nonce.
>
> If there's nobody else updating the same data, we could reuse the
> PUT/POST response and the ETag that came with it to make subsequent
> update. So we're still using a two-step update process, but the 2nd step
> of the first update may become the 1st step of the second update. See
> also the Concurrency Control section in the wiki page.
>
> Imagine this, you updated a user, then you went to do some other
> operations. Then you came back to this user and edited it again. If
> there's nobody else changing the user, then the new data and ETag that
> you got from the first update would still be valid. But if first update
> happened a long time ago, the client may decide according to the caching
> policy that the data has expired and then issue a GET to get a newer
> data and ETag.
>
OK - I like the idea that the etag returned by the PUT/POST can be used
for subsequent updates. We can go with this for now.
> >>> 11. In the PUT /tps/rest/config, we have requirements for having than
> >>> one user to approve changes. Admins make changes and agents approve
> >>> them if I recall correctly. You should look at the differences between
> >>> the agent and admin pages.
> >>
> >> I'll take a look again after I have the TPS instance back. Is there any
> >> documents or diagrams showing the workflow of all approval processes in
> >> TPS UI? Thanks.
> >>
> > The CC docs are probably the best bet for that (other than looking at
> > the code).
>
> The only approval process I saw in the UI is for profiles, not for
> general config. Could you point me to a specific page in the docs?
>
Yeah - I think thats right actually. All of the stuff thats in config
did not require two agent approval.
> Thanks.
>
More information about the Pki-devel
mailing list