Merge lp:~mbp/launchpad/dkim into lp:launchpad
| Status: | Merged | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Approved by: | Jonathan Lange on 2010-11-25 | ||||||||
| Approved revision: | no longer in the source branch. | ||||||||
| Merged at revision: | 12008 | ||||||||
| Proposed branch: | lp:~mbp/launchpad/dkim | ||||||||
| Merge into: | lp:launchpad | ||||||||
| Diff against target: |
914 lines (+267/-117) 9 files modified
lib/canonical/launchpad/doc/emailauthentication.txt (+16/-10) lib/canonical/launchpad/mail/handlers.py (+54/-49) lib/canonical/launchpad/mail/helpers.py (+20/-2) lib/canonical/launchpad/mail/tests/test_handlers.py (+61/-0) lib/lp/bugs/tests/bugs-emailinterface.txt (+39/-36) lib/lp/services/mail/incoming.py (+28/-5) lib/lp/services/mail/tests/incomingmail.txt (+24/-13) lib/lp/services/mail/tests/test_incoming.py (+24/-1) utilities/migrater/file-ownership.txt (+1/-1) |
||||||||
| To merge this branch: | bzr merge lp:~mbp/launchpad/dkim | ||||||||
| Related bugs: |
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Jonathan Lange (community) | 2010-11-25 | Approve on 2010-11-25 | |
| Graham Binns | code | 2010-11-25 | Pending |
| Launchpad code reviewers | 2010-11-25 | Pending | |
|
Review via email:
|
|||
This proposal supersedes a proposal from 2010-11-24.
Commit Message
[r=jml][ui=none][bug=316272,643200,643219] DKIM authentication for incoming email
Description of the Change
This fixes a few more things related to authentication of incoming mail:
* gpg signature timestamp checks should cover all mail, not just that to malone (bug 643200)
* checks on mail to new@ should make sure it's strongly authenticated, not specifically that it has a gpg signature (bug 643219)
* there was no test that gpg mail with implausible timestamps was actually rejected afaics
I haven't interactively tested this and I'm not utterly confident in the existing test coverage, so please review carefully and test it interactively yourself if you know how.
MaloneHandler.
Thanks
| Māris Fogels (mars) wrote : | # |
| Jonathan Lange (jml) wrote : | # |
Hey Martin,
I like the refactoring that extracts extractAndAuthe
As a general point, we insist on capitalized sentences with full stops in our comments and docstrings.
I'm finding it hard to grok test_NonGPGNewBug. Your comment there is helpful, but I think it would help me trust the test more if there were reasons for why you aren't doing the normal thing and why you are logging in directly instead.
Also, you'll need to change all of the first person references. Nothing more frustrating to wonder who "I" is.
I also don't know how to make a GPG signature with crazy timestamps. It would be nice to do that instead of checking that the checker is called. The test you've got is OK to land though.
jml
| Jonathan Lange (jml) wrote : | # |
I was going to say, I think I'd appreciate a second review from someone who knows mail (or bug mail) better before this lands.
| Martin Pool (mbp) wrote : | # |
I'll add this text, is it more clear:
"""Mail authenticated other than by gpg can create bugs.
The incoming mail layer is responsible for authenticating the mail,
and setting the current principal to the sender of the mail, either
weakly or non-weakly authenticated. At the layer of the handler,
which this class is testing, we shouldn't care by what mechanism we
decided to act on behalf of the mail sender, only that we did.
In bug 643219, Launchpad had a problem where the MaloneHandler code
was puncturing that abstraction and directly looking at the GPG
signature; this test checks it's fixed.
"""
| Graham Binns (gmb) wrote : | # |
Sorry Martin, I didn't get time to review this today. I'll try to take
a look at it tomorrow morning.
--
Graham Binns
http://
| Graham Binns (gmb) wrote : | # |
I'm happy for this to land (apologies for taking so long to review it). I'm not convinced that I'm competent enough to test this interactively locally, so I suggest that we get the LP team to give the tyres a good kicking when it gets onto staging instead.
| Martin Pool (mbp) wrote : | # |
@gmb Could you please land this for me? Thanks.
| Graham Binns (gmb) wrote : | # |
On 29 September 2010 03:31, Martin Pool <email address hidden> wrote:
> @gmb Could you please land this for me? Thanks.
Sure thing.
| Martin Pool (mbp) wrote : | # |
OK, this is now updated with the following changes based on the full-testsuite failure, and the tests in bugs-emailinter
* There is a lack of coherence between some things checking for a .signature and some checking the current security principal. the email doctests had some trouble with this; specifically they didn't make the principal weaklyauthenticated before testing that condition. This is now fixed.
* Typically for doctests, state is run together across tests, so I cleared the mail queue so we'd get a more obvious failure.
* The not-gpg-signed error template was misnamed and will become more so in future, so I renamed it. The error is not so much about being unsigned, but being unauthenticated when trying to create a new bug.
Here's the incremental diff:
=== renamed file 'lib/canonical/
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
@@ -94,12 +94,15 @@
commands = self.getCommand
to_user, to_host = to_addr.split('@')
+ if to_user.lower() == 'new':
+ # Special failure message for unauthenticated attempts to create
+ # new bugs.
+ ensure_
+ 'unauthenticate
if len(commands) > 0:
if to_user.lower() == 'new':
# A submit request.
- ensure_
- 'not-gpg-
elif to_user.isdigit():
# A comment to a bug. We set add_comment_to_bug to True so
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
@@ -211,7 +211,11 @@
def ensure_
- """Make sure that the current principal is not weakly authenticated."""
+ """Make sure that the current principal is not weakly authenticated.
+
+ NB: This mixes checking properties of the message with properties of the
+ current principal; it's assumed that this message was just received.
+ """
cur_principal = get_current_
# The security machinery doesn't know about
# IWeaklyAuthenti
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -339,13 +339,15 @@
... IWeaklyAuthenti
...
| Martin Pool (mbp) wrote : | # |
I'll run the tests for this here; if I could get an additional review that would be nice.
| Martin Pool (mbp) wrote : | # |
There are further failures in emailauthentica
I tried running ./bin/test mail but that didn't seem to get this before.
| Jonathan Lange (jml) wrote : | # |
On Fri, Oct 1, 2010 at 9:20 AM, Martin Pool <email address hidden> wrote:
> OK, this is now updated with the following changes based on the full-testsuite failure, and the tests in bugs-emailinter
>
> * There is a lack of coherence between some things checking for a .signature and some checking the current security principal. the email doctests had some trouble with this; specifically they didn't make the principal weaklyauthenticated before testing that condition. This is now fixed.
>
> * Typically for doctests, state is run together across tests, so I cleared the mail queue so we'd get a more obvious failure.
>
> * The not-gpg-signed error template was misnamed and will become more so in future, so I renamed it. The error is not so much about being unsigned, but being unauthenticated when trying to create a new bug.
>
> Here's the incremental diff:
>
Thanks for persisting with this. There are a couple of points where
I'm not clear on what's going on and a couple of minor tweaks.
> === renamed file 'lib/canonical/
> === modified file 'lib/canonical/
> --- lib/canonical/
> +++ lib/canonical/
> @@ -94,12 +94,15 @@
> commands = self.getCommand
> to_user, to_host = to_addr.split('@')
> add_comment_to_bug = False
> + if to_user.lower() == 'new':
> + # Special failure message for unauthenticated attempts to create
> + # new bugs.
> + ensure_
> + 'unauthenticat
Why do you need to two clauses for "to_user.lower() == 'new'"? I can't
figure it out from the code. Perhaps there should be a comment.
> if len(commands) > 0:
> ensure_
> if to_user.lower() == 'new':
> # A submit request.
> - ensure_
> - 'not-gpg-
> commands.insert(0, BugEmailCommand
> elif to_user.isdigit():
> # A comment to a bug. We set add_comment_to_bug to True so
>
> === modified file 'lib/canonical/
> --- lib/canonical/
> +++ lib/canonical/
> @@ -211,7 +211,11 @@
> def ensure_
> error_template=
> no_key_
> - """Make sure that the current principal is not weakly authenticated."""
> + """Make sure that the current principal is not weakly authenticated.
> +
> + NB: This mixes checking properties of the message with properties of the
> + current principal; it's assumed that this message was just received.
> + "...
| Martin Pool (mbp) wrote : | # |
On 1 October 2010 23:33, Jonathan Lange <email address hidden> wrote:
> On Fri, Oct 1, 2010 at 9:20 AM, Martin Pool <email address hidden> wrote:
>> OK, this is now updated with the following changes based on the full-testsuite failure, and the tests in bugs-emailinter
>>
>> * There is a lack of coherence between some things checking for a .signature and some checking the current security principal. the email doctests had some trouble with this; specifically they didn't make the principal weaklyauthenticated before testing that condition. This is now fixed.
>>
>> * Typically for doctests, state is run together across tests, so I cleared the mail queue so we'd get a more obvious failure.
>>
>> * The not-gpg-signed error template was misnamed and will become more so in future, so I renamed it. The error is not so much about being unsigned, but being unauthenticated when trying to create a new bug.
>>
>> Here's the incremental diff:
>>
>
> Thanks for persisting with this. There are a couple of points where
> I'm not clear on what's going on and a couple of minor tweaks.
>
>> === renamed file 'lib/canonical/
>> === modified file 'lib/canonical/
>> --- lib/canonical/
>> +++ lib/canonical/
>> @@ -94,12 +94,15 @@
>> commands = self.getCommand
>> to_user, to_host = to_addr.split('@')
>> add_comment_to_bug = False
>> + if to_user.lower() == 'new':
>> + # Special failure message for unauthenticated attempts to create
>> + # new bugs.
>> + ensure_
>> + 'unauthenticat
>
> Why do you need to two clauses for "to_user.lower() == 'new'"? I can't
> figure it out from the code. Perhaps there should be a comment.
I'll add a comment. It's because we need to check for authentication
on mails that either attempt to create a new bug or that have commands
that modify an existing bug, and we give a different error in either
case. After doing this, we must check the recipient address is
recognized, and that again includes the case of 'new@'.
Perhaps I should try harder to refactor this...?
>> if len(commands) > 0:
>> ensure_
>> if to_user.lower() == 'new':
>> # A submit request.
>> - ensure_
>> - 'not-gpg-
>> commands.insert(0, BugEmailCommand
>> elif to_user.isdigit():
>> # A comment to a bug. We set add_comment_to_bug to True so
>>
>
>
>> === modified file 'lib/canonical/
>> --- lib/canonical/
>> +++ lib/canonical/
>> @@ -211,7 +211,11 @@
>> def ensure_
| Martin Pool (mbp) wrote : | # |
On 8 October 2010 12:19, Martin Pool <email address hidden> wrote:
> On 1 October 2010 23:33, Jonathan Lange <email address hidden> wrote:
>> On Fri, Oct 1, 2010 at 9:20 AM, Martin Pool <email address hidden> wrote:
>>> === renamed file 'lib/canonical/
>>> === modified file 'lib/canonical/
>>> --- lib/canonical/
>>> +++ lib/canonical/
>>> @@ -94,12 +94,15 @@
>>> commands = self.getCommand
>>> to_user, to_host = to_addr.split('@')
>>> add_comment_to_bug = False
>>> + if to_user.lower() == 'new':
>>> + # Special failure message for unauthenticated attempts to create
>>> + # new bugs.
>>> + ensure_
>>> + 'unauthenticat
>>
>> Why do you need to two clauses for "to_user.lower() == 'new'"? I can't
>> figure it out from the code. Perhaps there should be a comment.
>
> I'll add a comment. It's because we need to check for authentication
> on mails that either attempt to create a new bug or that have commands
> that modify an existing bug, and we give a different error in either
> case. After doing this, we must check the recipient address is
> recognized, and that again includes the case of 'new@'.
>
> Perhaps I should try harder to refactor this...?
I think it's a bit simpler now. You could tear it apart entirely
which could be nice but this branch is old...
>>> @@ -211,7 +211,11 @@
>>> def ensure_
>>> error_template=
>>> no_key_
>>> - """Make sure that the current principal is not weakly authenticated."""
>>> + """Make sure that the current principal is not weakly authenticated.
>>> +
>>> + NB: This mixes checking properties of the message with properties of the
>>> + current principal; it's assumed that this message was just received.
>>> + """
>>
>> I can't say the expansion clears things up much for me.
Cleaner like this:
def ensure_
"""Make sure that the current principal is not weakly authenticated.
NB: While handling an email, the authentication state is stored partly in
properties of the message object, and partly in the current security
principal. As a consequence this function will only work correctly if the
message has just been passed through authenticateEmail -- you can't give
it an arbitrary message object.
"""
>> Could you please use lp.testing.
>> '<email address hidden>'? We're trying to kill off some of our more
>> gratuitous magic literals.
>
> sure, thanks
I've removed all the occurr...
| Jonathan Lange (jml) wrote : | # |
Thanks Martin.
From your comments, things look good, but I don't see any new revisions pushed up. As soon as you'll push them up I'll give them the once over and probably approve for landing.
| Martin Pool (mbp) wrote : | # |
> Thanks Martin.
>
> From your comments, things look good, but I don't see any new revisions pushed
> up. As soon as you'll push them up I'll give them the once over and probably
> approve for landing.
I don't know why they didn't show up in the merge proposal discussion thread on the web page, but the new revisions (from Friday the 15th) are in the branch, are visible in 'unmerged revisions' and in the diff.
| Martin Pool (mbp) wrote : | # |
Looking at it again, I'm not sure if the handling of new@ is really correct,
but the tests should tell us.
- Martin
On 19/10/2010 7:38 PM, "Jonathan Lange" <email address hidden> wrote:
Review: Approve
--
https:/
You are the owner of lp:~mbp/launch...
| Jonathan Lange (jml) wrote : | # |
Martin, what's the next step here?
| Martin Pool (mbp) wrote : | # |
On 5 November 2010 05:35, Jonathan Lange <email address hidden> wrote:
> Martin, what's the next step here?
I would like someone to review the currently proposed changes, and if
they are acceptable to sponsor landing. Thanks.
--
Martin
| Jonathan Lange (jml) wrote : | # |
I approved on 2010-10-19. Have there been changes since? If not, I'm happy to land this for you.
| Martin Pool (mbp) wrote : | # |
On 7 November 2010 22:34, Jonathan Lange <email address hidden> wrote:
> I approved on 2010-10-19. Have there been changes since? If not, I'm happy to land this for you.
Just confirming what I said on irc: there are no changes since. I'm
going to run the full test suite it in a VM, but if you could also
submit it in parallel with that, I'd appreciate it. If it fails,
please let me know.
--
Martin
| Martin Pool (mbp) wrote : | # |
My attempt to test it was thwarted by bug 629746 causing 'make check'
to fail. I'll try again with bin/test.
| Jonathan Lange (jml) wrote : | # |
Conflicts again!
Text conflict in lib/canonical/
Text conflict in lib/lp/
Text conflict in lib/lp/
I can't run the tests on ec2 until they are fixed. Sorry.
| Jonathan Lange (jml) wrote : | # |
Still waiting for conflict resolution.
| Martin Pool (mbp) wrote : | # |
OK, now resolved, and I'm trying to persuade the tests to run.
| Martin Pool (mbp) wrote : | # |
This apparently has some doctest failures:
Failure in test lib/lp/
Traceback (most recent call last):
File "/usr/lib/
testMethod()
File "/usr/lib/
raise self.failureExc
AssertionError: Failed doctest test for incomingmail.txt
File "lib/lp/
-------
File "lib/lp/
Failed example:
handleMail(
Differences (ndiff with -expected +actual):
- WARNING:
- WARNING:
- WARNING:
- WARNING:
+ ERROR:canonical
+ http://
+ Traceback (most recent call last):
+ File "/home/
+ principal = authenticateEma
+ File "/home/
+ 'incoming mail verification')
+ File "/home/
+ raise IncomingEmailEr
+ IncomingEmailError: The message you sent included commands to modify the incoming mail verification, but the
+ signature was (apparently) generated too far in the past or future.
+ <BLANKLINE>
....
| Martin Pool (mbp) wrote : | # |
More failures in http://
| Jonathan Lange (jml) wrote : | # |
I ran the tests against ec2 – you should have received the email – and have got the same errors.
Do you need help debugging them?
| Martin Pool (mbp) wrote : | # |
On 21 November 2010 05:28, Jonathan Lange <email address hidden> wrote:
> I ran the tests against ec2 – you should have received the email – and have got the same errors.
>
> Do you need help debugging them?
Thanks, I think I'm ok. Will try to do it Monday.
--
Martin
| Martin Pool (mbp) wrote : | # |
Thanks for all your patience and help. The updated branch now passes at least the two doctests that were identified as failing. The specific change is that I've gone back to the approach of passing in the timestamp-checking callback, but moved it to a more appropriate spot that (I think) covers all cases. This is imo cleaner than monkey patching, as I was doing.
I'm thinking of also retargeting this to devel. It has no database dependencies.
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
@@ -20,12 +20,18 @@
>>> commit()
>>> LaunchpadZopele
+For most of these tests, we don't care whether the timestamps are out of
+date:
+
+ >>> def accept_
+ ... pass
+
Now Sample Person and Foo Bar have one OpenPGP key each. Next, let's get
a test email that's signed and try to authenticate the user who sent it:
>>> from canonical.
>>> msg = read_test_
- >>> principal = authenticateEma
+ >>> principal = authenticateEma
If the user isn't registered in Launchpad, None is return, if it
succeeds the authenticated principal:
@@ -52,7 +58,7 @@
message. Inline signatures are supported as well.
>>> msg = read_test_
- >>> principal = authenticateEma
+ >>> principal = authenticateEma
>>> principal is not None
True
>>> name, addr = email.Utils.
@@ -65,7 +71,7 @@
As well as signed multipart messages:
>>> msg = read_test_
- >>> principal = authenticateEma
+ >>> principal = authenticateEma
>>> principal is not None
True
>>> name, addr = email.Utils.
@@ -80,7 +86,7 @@
to deal with it if we receive a dash escaped message.
>>> msg = read_test_
- >>> principal = authenticateEma
+ >>> principal = authenticateEma
>>> principal is not None
True
>>> name, addr = email.Utils.
@@ -96,7 +102,7 @@
>>> msg = read_test_
>>> name, addr = email.Utils.
>>> from_user = getUtility(
- >>> principal = authenticateEma
+ >>> principal = authenticateEma
Traceback (most recent call last):
...
InvalidSig
@@ -131,7 +137,7 @@
... msg = email.message_
... line_ending.
... msg.parsed_string = msg.as_string()
- ... principal = authenticateEma
+ ... principal = authenticateEma
... authenticated_
| Jonathan Lange (jml) wrote : | # |
The branch has massive sample data changes. What's up with that?
| Martin Pool (mbp) wrote : | # |
On 24 November 2010 22:35, Jonathan Lange <email address hidden> wrote:
> The branch has massive sample data changes. What's up with that?
I wish I knew. I started from db-devel (because of it being called
lp:launchpad), and I just merged devel again yesterday.
--
Martin
| Martin Pool (mbp) wrote : | # |
16th time's a charm?
This is now rebased on to devel, which should get rid of the sampledata changes caused by integrating db-devel. Aside from that there are few changes from the previously reviewed version, but another scan could be good.
It passes './bin/test -t mail' and I'm just running a local full bin/test to see if that finds any other problems.
| Martin Pool (mbp) wrote : | # |
How silly. I did have these errors before, but the spurious errors from mailman caused me to overlook it. Could someone please resubmit it?

Hi Martin,
I asked Deryck about who may have domain expertise in this:
<mars> deryck, I was wondering if someone on your team would have knowledge in that domain that could help Martin out?
<deryck> mars, perhaps gmb or allenap. But the code team should have some expertise there, too. abentley wrote BaseMailer, I believe.
<mars> deryck, great. thank you for the help
<deryck> np
I suggest you ping one of the people above. They are on either side of your day.