Merge lp:~adeuring/launchpad/authentication-for-private-products into lp:launchpad
| Status: | Rejected |
|---|---|
| Rejected by: | Abel Deuring on 2012-10-12 |
| Proposed branch: | lp:~adeuring/launchpad/authentication-for-private-products |
| Merge into: | lp:launchpad |
| Diff against target: |
1561 lines (+580/-109) 34 files modified
lib/lp/answers/tests/test_question_webservice.py (+5/-3) lib/lp/app/model/launchpad.py (+1/-1) lib/lp/blueprints/browser/tests/test_specification.py (+11/-4) lib/lp/blueprints/browser/tests/test_views.py (+1/-1) lib/lp/blueprints/tests/test_webservice.py (+6/-4) lib/lp/bugs/browser/tests/test_bugtask.py (+2/-2) lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt (+2/-1) lib/lp/bugs/stories/bugs/xx-bug-personal-subscriptions-advanced-features.txt (+2/-1) lib/lp/bugs/stories/patches-view/patches-view.txt (+2/-0) lib/lp/bugs/stories/structural-subscriptions/xx-advanced-features.txt (+2/-2) lib/lp/bugs/stories/webservice/xx-bug.txt (+5/-3) lib/lp/bugs/tests/test_bugs_webservice.py (+11/-6) lib/lp/bugs/tests/test_searchtasks_webservice.py (+3/-2) lib/lp/code/browser/tests/test_branch.py (+1/-1) lib/lp/code/browser/tests/test_product.py (+4/-2) lib/lp/code/stories/branches/xx-product-branches.txt (+5/-2) lib/lp/code/stories/webservice/xx-code-import.txt (+3/-2) lib/lp/registry/browser/tests/test_milestone.py (+4/-2) lib/lp/registry/browser/tests/test_pillar_sharing.py (+3/-3) lib/lp/registry/browser/tests/test_product.py (+1/-1) lib/lp/registry/configure.zcml (+27/-11) lib/lp/registry/interfaces/product.py (+36/-28) lib/lp/registry/model/product.py (+27/-1) lib/lp/registry/services/tests/test_sharingservice.py (+4/-2) lib/lp/registry/tests/test_pillaraffiliation.py (+1/-1) lib/lp/registry/tests/test_product.py (+340/-2) lib/lp/registry/tests/test_product_webservice.py (+22/-13) lib/lp/registry/tests/test_subscribers.py (+4/-1) lib/lp/security.py (+29/-0) lib/lp/testing/factory.py (+3/-3) lib/lp/testing/pages.py (+3/-1) lib/lp/translations/browser/tests/test_noindex.py (+6/-1) lib/lp/translations/stories/importqueue/xx-entry-details.txt (+2/-1) lib/lp/translations/stories/webservice/xx-potemplate.txt (+2/-1) |
| To merge this branch: | bzr merge lp:~adeuring/launchpad/authentication-for-private-products |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Curtis Hovey (community) | code | 2012-10-10 | Needs Fixing on 2012-10-10 |
|
Review via email:
|
|||
Description of the Change
This branch is my second attempt to activate permission checks for private products. The first attempt caused numerous OOPSes when it was deployed last monday. The reason was that the security adapter also refused access to most IProduct properties for inactive products, but in some cases details about inactive products are needed during page rendering, even if they are not visible for unprivileged users.
I discussed several approaches to fix this problem with sinzui; it turned out that we should for now simply allow access to the properties that are needed. Better fixes would need to long to implement.
The diff against trunk is pretty long. But r16117 simply adds the the changed from r16090 that were reverted in r16112.
tests:
./bin/test -vvt lp.registry.
./bin/test -vvt lp.registry.
./bin/test -vvt lp.registry.
no lint
| Abel Deuring (adeuring) wrote : | # |
| Curtis Hovey (sinzui) wrote : | # |
The comment format is
XXX: Abel Deuring 2012-10-10 bug=1065162
There is still something wrong and we think are missing tests. non-registry users and anonymous users get 403 on pages that that are working with deactivated projects.
1. Start an Lp instance
2. As admin, https:/
and verify redfish and thunderbird are in the affected table.
3. Visit https:/
4. Visit https:/
and deactivate thunderbird
5. Visit https:/
and verify thunderbird is listed.
6. Follow the link to https:/
and verify it says it is deactivated
7. Visit https:/
and verify that only redfish is shown in the tasks table.
8. As no-priv, visit https:/
and verify the page is a 404.
9. Visit https:/
and verify that only redfish is shown in the tasks table.
BAD: the user gets a 403!
OH, this loads after a while...we have a async issue?
Module lp.bugs.
self.target_parent = target.project
Unauthorized: (<Product at 0x2b15b8d98410>, 'project', 'launchpad.View'
10. Visit https:/
and verify thunderbird is listed.
BAD: the user gets a 403!
if IHasIcon.
Unauthorized: (<Product at 0x2b15bca1fd10>, 'icon', 'launchpad.View')
11. As anonymous, visit https:/
and verify the page is a 404.
12. Visit https:/
and verify that only redfish is shown in the tasks table.
BAD: the user gets a 403!
OH, this loads after a while...we have a async issue?
Module lp.bugs.
self.target_parent = target.project
Unauthorized: (<Product at 0x2b15b8d98410>, 'project', 'launchpad.View'
13. Visit https:/
...I cannot. Lp requires me to login to see a page intended for bots and anonymous users.
This kind of error can be seen elsewhere where deactivated projects can appear in Lp. In qastaging for example we can deactivate a project listed on Lp's front page ans the page still displays for anonymous and non-registry users, but devel breaks with your branch.
I think we want to make the security checker smarter so we can land this branch to maintain the current behaviour. We can revise the checker and the interfaces in future branches. Maybe both checkAuthentica
| Abel Deuring (adeuring) wrote : | # |
I think we should not return True for inactive products. In that case, oridnary users will be able to see these inactive products. Or we separate the checkers for IPillar and IProductView. But as we discussed in a hangout, I had a hard time to implement this when the permission lp.View is used both for IPillar and IProductView.
| Curtis Hovey (sinzui) wrote : | # |
Members of ~registry, ~admins, and ~commercial-admins *do* have lp.view on deactivated projects now. They also have lp.moderate and some have lp.admin and lp.edit. So we will return true for deactivated project for about 100 people.
| Abel Deuring (adeuring) wrote : | # |
On 10.10.2012 21:52, Curtis Hovey wrote:
> Members of ~registry, ~admins, and ~commercial-admins *do* have lp.view on deactivated projects now. They also have lp.moderate and some have lp.admin and lp.edit. So we will return true for deactivated project for about 100 people.
yes, but my point are the permissions for ordinary users: I could simply
not find a way to use lp.View both for IPillar and for IProductView so
that an oridnary users sees a 404 error when visiting the main page of a
deactivated product
I'd be grateful for a hint how to do this.
| Curtis Hovey (sinzui) wrote : | # |
This is the checker used in production:
class ViewPillar(
usedfor = IPillar
permission = 'launchpad.View'
def checkUnauthenti
return self.obj.active
def checkAuthentica
"""The Admins & Commercial Admins can see inactive pillars."""
if self.obj.active:
return True
else:
return (user.in_
You introduced a new checker that is specific to IProduct, but is does not ever consider .active. As is said in the hangout, IPillar is not properly implemented. IDistribution.
class ViewProduct(
permission = 'launchpad.View'
usedfor = IProduct
def checkAuthentica
if self.obj.
return super(ViewProduct, self).checkAuth
return (user.in_
or user.in_admin
or self.obj.
def checkUnauthenti
if self.obj.
return super(ViewProduct, self).checkUnau
return False
| Abel Deuring (adeuring) wrote : | # |
On 10.10.2012 22:30, Curtis Hovey wrote:
> This is the checker used in production:
>
> class ViewPillar(
> usedfor = IPillar
> permission = 'launchpad.View'
>
> def checkUnauthenti
> return self.obj.active
>
> def checkAuthentica
> """The Admins & Commercial Admins can see inactive pillars."""
> if self.obj.active:
> return True
> else:
> return (user.in_
> user.in_admin or
> user.in_
>
> You introduced a new checker that is specific to IProduct, but is does not ever consider .active.
The one in r16090 did.
> As is said in the hangout, IPillar is not properly implemented. IDistribution.
>
> class ViewProduct(
> permission = 'launchpad.View'
> usedfor = IProduct
>
> def checkAuthentica
> if self.obj.
> return super(ViewProduct, self).checkAuth
...this would deny access to properties like name, displayname etc which
we need for deactivated products, so the same problem we had with r16090.
> return (user.in_
> or user.in_admin
> or self.obj.
>
> def checkUnauthenti
> if self.obj.
> return super(ViewProduct, self).checkUnau
> return False
>
| William Grant (wgrant) wrote : | # |
Have you considered feature-flagging this so we can revert easily if necessary? It may also be helpful to later make projects show up as <redacted> and raise a soft OOPS as private teams do today, although that will be less helpful as a lot of artifact URLs contain the project name.
| Abel Deuring (adeuring) wrote : | # |
On 10.10.2012 23:53, William Grant wrote:
> Have you considered feature-flagging this so we can revert easily if necessary? It may also be helpful to later make projects show up as <redacted> and raise a soft OOPS as private teams do today, although that will be less helpful as a lot of artifact URLs contain the project name.
>
Do we have means to change ZCML configurations via feature flags? The
main issue are new permissions and a changed inheritance hierarchy for
IProduct.
| William Grant (wgrant) wrote : | # |
AIUI the main thing launchpad.View on IProduct is used for today is to prevent traversal to deactivated products. If you add an extra guard to prevent such traversal even if launchpad.View is held, then the launchpad.View adapter can have an emergency feature flag which grants it to everyone.
| Abel Deuring (adeuring) wrote : | # |
On 11.10.2012 10:40, William Grant wrote:
> AIUI the main thing launchpad.View on IProduct is used for today is to prevent traversal to deactivated products. If you add an extra guard to prevent such traversal even if launchpad.View is held, then the launchpad.View adapter can have an emergency feature flag which grants it to everyone.
>
A feature flag alone would not help much. I think the main issue is
that the same checker is used for IPillar and IProductLimitedView
(should be renamed to IProductView, but this is different issue).
Let me try to explain the problem with this branch:
lp:~adeuring/launchpad/authentication-for-private-products-test
It has my core changes: most of attributes of IProduct are defined in
IProductLimitedView and require the permission launchpad.View.
The relevant security adapter is ViewProduct.
First, the variant r16120:
The section for Product in registry/
any directive for IPillar.
Now do "make run", log in as <email address hidden> and try to view any
product related page. You'll get "LocationError:
(<Product at 0xba970d0>, 'active')<br />"
Or run iharness:
from lp.registry.
p = getUtility(
p.active
You'll get a ForbiddenAttribute exception.
So we need a directive for IPillar in registry/
r16121 has
<allow
The iharness test now works.
Now "make run", log in as an admin and make thunderbird private, as
suggested by Curtis.
Visit https:/
and without being logged in. This works as expected: The admin sees
the regular page with the notice "this project is currently inactive."
Anonymous and <email address hidden> see a 404 page.
Now visit https:/
task for thunderbird.)
Anonymous and the admin see the page just fine, but <email address hidden>
gets a "Not allowed here" error:
Unauthorized: (<Product at 0x2b0588b8d9d0>, 'project',
'launchpad.
as noticed by Curtis.
Now let us try to remove the check for inactive products in the
security adapter, as suggested by William (out of lazyness, without a
feature flag, i just removed the check for inactive products): r16122
The bug page works fine for all users, but anonymous and
test@canoncial,com no longer get the 404 error for
https:/
the admin: "This project is currently inactive."
So, no luck either.
Let us now require the permission lp.View for IPillar: r16123
Both pages, https:/
https:/
and <email address hidden> .
Let's reenable the check for inactive products in ViewProduct: r16124
Now anonymous and <email address hidden> get again the 404 error for
https:/
a 403 for https:/
at the situation that required a rollback of r16090 of trunk.
I think the main problem is that the inte...
Unmerged revisions
- 16119. By Abel Deuring on 2012-10-10
-
trunk merged.
- 16118. By Abel Deuring on 2012-10-10
-
avoid OOPSes when data of inactive products is needed for users without special permissions.

the "real" changes:
=== modified file 'lib/lp/ registry/ configure. zcml' registry/ configure. zcml 2012-10-09 10:28:02 +0000 registry/ configure. zcml 2012-10-10 18:04:36 +0000
class= "lp.registry. model.product. Product" >
interface ="lp.registry. interfaces. product. IProductPublic" /> "lp.registry. interfaces. pillar. IPillar" /> "launchpad. View" "lp.registry. interfaces. product. IPillar" />
permissio n="launchpad. View"
interface ="lp.registry. interfaces. product. IProductLimited View"/>
--- lib/lp/
+++ lib/lp/
@@ -1229,8 +1229,9 @@
<allow
- <allow
- interface=
+ <require
+ permission=
+ interface=
<require
@@ -1371,8 +1372,9 @@
<!-- IStructuralSubs criptionTarget -->
- <require "launchpad. View"
interface ="lp.bugs. interfaces. structuralsubsc ription. IStructuralSubs criptionTargetR ead" />
permissio n="launchpad. AnyAllowedPerso n"
- permission=
+ <!-- XXX bug=1065162 Abel Deuring 2012-10-10:
+ This interface should require the permission launchpad.View. -->
+ <allow
<require
=== modified file 'lib/lp/ registry/ interfaces/ product. py' registry/ interfaces/ product. py 2012-10-09 10:28:02 +0000 registry/ interfaces/ product. py 2012-10-10 18:04:36 +0000
--- lib/lp/
+++ lib/lp/
@@ -430,6 +430,24 @@
def userCanView(user):
"""True if the given user has access to this product."""
+ # bug=1065162 Abel Deuring 2012-10-10: name_validator, _("""The name of the project as it would appear in a as='display_ name')
+ # name and displayname should be defined in IProductLimitedView
+ name = exported(
+ ProductNameField(
+ title=_('Name'),
+ constraint=
+ description=_(
+ "At least one lowercase letter or number, followed by "
+ "letters, numbers, dots, hyphens or pluses. "
+ "Keep this name short; it is used in URLs as shown above.")))
+
+ displayname = exported(
+ TextLine(
+ title=_('Display Name'),
+ description=
+ paragraph.""")),
+ exported_
+
class IProductLimited View( esDirectly, IHasAppointedDr iver, IHasBranches,
IBugTarget, ICanGetMileston
@@ -491,22 +509,6 @@
"required because there might be a project driver and also a "
"driver appointed in the overarching project group.")
- name = exported( name_validator, _("""The name of the project as it would appear in a as='display_ name')
title= _('Title' ),
- ProductNameField(
- title=_('Name'),
- constraint=
- description=_(
- "At least one lowercase letter or number, followed by "
- "letters, numbers, dots, hyphens or pluses. "
- "Keep this name short; it is used in URLs as shown above.")))
-
- displayname = exported(
- TextLine(
- title=_('Display Name'),
- description=
- paragraph.""")),
- exported_
-
title = exported(
Title(
=== modified file 'lib/lp/ registry/ tests/test_ product. py'
--- lib/lp/registry...