1.8.0 breaks login_with() API compat with existing credentials files, and forces keyrings

Bug #686690 reported by Martin Pitt
12
This bug affects 1 person
Affects Status Importance Assigned to Milestone
launchpadlib
Fix Released
High
Leonard Richardson

Bug Description

1.8.0 got a new feature to use python-keyring instead of the classic credentials file. However, it suddenly uses that by default for the existing login_with() method. Given that login_with() has been the primary API for logging into Launchpad, by the documentation, talks, and example scripts, this now

 - breaks noninteractivity of pretty much all existing scripts and cron jobs, as it now insists on using a keyring password
 - breaks existing credential files, including dropping of the credentials_file argument and access levels
 - make it much harder to pass around credentials, as they aren't files in a well-known place any more.

Please, pretty please revert this to the original behaviour. If you introduce a new authentication system, then please use a new API for this, such as login_with_keyring().

tags: added: desktop-integration regression
Changed in launchpadlib:
importance: Undecided → High
Gary Poster (gary)
Changed in launchpadlib:
status: New → Triaged
Revision history for this message
Martin Pitt (pitti) wrote :

We had a quick discussion in #launchpad-dev. I think for the backwards compatibility support it would be enough if existing credentials files and the credentials_file argument would work again, and the keyring could be made optional.

Benji said that 1.8.0 is meant to be used with python-keyring 0.5. We currently have 0.2 in the archive (it's essentially unmaintained in Debian/Ubuntu), that could explain my problems with it. 0.5 drops its own gnome-keyring module and uses the proper library instead.

Revision history for this message
Martin Pitt (pitti) wrote :

Oh, and I suddenly got a ~/crypted_pass.cfg file now. This certainly shouldn't live right in my home directory, but in ~/.cache/ or ~/.config (depending on how volatile that is). Is that a python-keyring or a launchpadlib bug?

summary: - 1.8.0 completely breaks login_with() API (and forces keyrings)
+ 1.8.0 breaks login_with() API compat with existing credentials files,
+ and forces keyrings
Revision history for this message
Gary Poster (gary) wrote :

FWIW, Benji's comments in bug 686257 describe our expectations.

Given that we were wrong, Martin's suggestion sounds like the right direction to me. We had discussed such an approach earlier, but had hoped it would not be necessary.

I'd very much like anything passing a credentials_file argument to get a deprecation warning. I'd also like something like a deprecation warning if a credentials file is used, but I'm not sure if that is as reasonable. That said, a big concern with both is that these deprecations warn the wrong person, most of the time: users shouldn't have to worry about this. The devs of the code using launchpadlib should.

Revision history for this message
Martin Pitt (pitti) wrote :

Since you want to add deprecation warnings, is the intent that credentials files should actually be dropped at some point and be replaced with keyrings only? Where are these key rings saved, so that they can be transfered from one computer to the next if necessary?

Revision history for this message
Gary Poster (gary) wrote :

Per flacoste, we're changing as you requested at the start of this bug: revert the login_with changes, add a new function for the keyring library, and strongly encourage all important interactive programs, with special attention for apport, ground control, quickly, and hydrazine, to use the new API in natty.

Changed in launchpadlib:
assignee: nobody → Benji York (benji)
Revision history for this message
Martin Pitt (pitti) wrote :

Thanks!

Note: apport isn't an interactive desktop app in the launchpadlib sense; it doesn't use launchpadlib on the clients at all. This just happens in the data center, in the crash reprocessing bot.

Revision history for this message
Leonard Richardson (leonardr) wrote :

We broke backwards compatibility when we removed the ability to store credentials in an unencrypted store. We did this deliberately, but we didn't consider that a cronjob needs to get credentials without any user input.

I don't think you can completely separate the "load from file" case from the "open a browser" case. You're assuming a file with the credentials already exists. What if it doesn't exist? How does it get created in the first place? You have to open a browser.

Consider a launchpadlib script foo.py. I might run it as a cronjob and you might run it manually every once in a while. The code is the same, but the context is different. Because of this, I don't think it makes sense to have a separate path through login_with() for scripts that are run as cronjobs. You shouldn't have an unencrypted credential lying around on your computer just because I like to run the script as a cronjob on my computer.

I have two ideas:

Idea #1: Let's package a script with launchpad that does the browser open and writes the unencrypted credential to disk. If you need to run launchpadlib cronjobs, you run this script. If you don't, you don't.

---
$ python launchpadlib/contrib/create_unencrypted_credential.py
You're about to authorize a Launchpad credential that will be stored *unencrypted* in /home/leonardr/.cache/launchpadlib-credential.
With this credential in place, you can run cronjobs that use launchpadlib.
But, anyone with access to your computer will be able to access your Launchpad account.
Are you sure you want to do this? [Y/n] Y
The authorization page:
 (http://launchpad.net/...)
should be opening in your browser. Use your browser to authorize\nthis program to access Launchpad on your behalf.
Waiting to hear from Launchpad about your decision...

[The browser opens up and I authorize the desktop integration.]

Your unencrypted credential is stored in /home/leonardr/.cache/launchpadlib-credential
---

login_with() would check the GNOME keyring, then the KDE wallet, then the encrypted file, then the unencrypted file.

Idea #2: We could change our usage of python-keyring so that if the GNOME Keyring and KDE Wallet are not available, the credential is written to an unencrypted file instead of an encrypted file. This would mean that GUI users get their credential encrypted, and console users don't.

You would still have to run a cronjob script manually, and use a console web browser to set up the credential. (I think there's a bug about console web browsers; we would fix that bug.) But after the first time, you'd never have to do that again for that machine.

I kind of prefer idea #1. "Run this script to set up cron access" is actually simpler than "Run your cron script once manually in a console environment." And console users who aren't interested in setting up cronjobs would still have their credential encrypted.

Revision history for this message
Leonard Richardson (leonardr) wrote :

BTW, if you run the setup script within a desktop environment whose keyring contains a credential for the appropriate Launchpad host, we can just copy that credential to an unencrypted file. There's no need to do another browser open.

Revision history for this message
Gary Poster (gary) wrote : Re: [Bug 686690] Re: 1.8.0 breaks login_with() API compat with existing credentials files, and forces keyrings

On Dec 13, 2010, at 6:15 PM, Leonard Richardson wrote:

> We broke backwards compatibility when we removed the ability to store
> credentials in an unencrypted store. We did this deliberately, but we
> didn't consider that a cronjob needs to get credentials without any user
> input.

If the new encrypted store were more powerful--if, for instance, the Gnome keychain had supported per-application credentials and generally had a better story--I think we might have had a better argument to support breaking backwards compatibility. As it is, the incremental improvement of our security is not convincing, in conversations externally or even when Benji and I talked over the situation.

AIUI, the big improvement between the old story and the new story is that, if someone were to steal your shut-down computer, they would not have easy access to your Launchpad authentication; and if someone were to root your machine, they would have a somewhat harder time getting to your password.

If they get your computer when you're machine is on and authenticated, the risk is essentially equivalent; if they install malware on your desktop, the risk is essentially equivalent; if they have rooted your machine, the risk is still not insignificant.

Is that increment worth breaking backward compatibility of cronscripts, which some people (Martin, for one, I believe) outnumber interactive scripts? Francis has gone on the side of "no". At the end of the day, it's a judgement call, and a balance.

When we consciously broke backwards compatibility, we also believed that the smooth interaction of interactive applications--Ground Control, Hydrazine, Quickly--was important to encourage. We felt that perhaps the combination of the security and the automatic increase of usability of interactive applications was worth it.

Again, it is a judgement call, and again, Francis has come down on the side of "no."

Barring Kees or someone else making a strong argument that the increment of security improvements warrants breaking backwards compatibility, we have our direction: make things backwards compatible.

Gary

Revision history for this message
Martin Pitt (pitti) wrote :
Download full text (3.2 KiB)

Leonard Richardson [2010-12-13 23:15 -0000]:
> I don't think you can completely separate the "load from file" case from
> the "open a browser" case. You're assuming a file with the credentials
> already exists. What if it doesn't exist? How does it get created in the
> first place? You have to open a browser.

Of course there needs to be an interaction once, for the initial
setup. You once run the cron job manually, then see that it stops at
the credential stage, and open the URL in your local browser. Once you
ack'ed the auth in Launchpad, you go back to your ssh window for the
server and press Enter there. Henceforth you'll have a credential file
on the server which isn't going to go away or become invalid.

The nice thing here is that there is no IP check or so, i. e. the
machine requesting LP access doesn't need to be the same machine that
has the browser open.

Alternatively you can create it locally and copy it to the server
(which is impossible if you locally use a GNOME keyring).

> You shouldn't have an unencrypted credential lying around on your
> computer just because I like to run the script as a cronjob on my
> computer.

I don't understand the rationale behind this. For server cron jobs we
need the unencrypted file, and on desktops it doesn't matter much, as
you can just always read the (unencrypted) cookie from your Browser
profile and use that to obtain a new credentials file.

> Idea #1: Let's package a script with launchpad that does the browser
> open and writes the unencrypted credential to disk. If you need to run
> launchpadlib cronjobs, you run this script. If you don't, you don't.
> [...]
>
> login_with() would check the GNOME keyring, then the KDE wallet, then
> the encrypted file, then the unencrypted file.

That would work mostly fine, I think. It would be great if
login_with() can continue to support the credentials_file argument, so
that you can put your auth file into a more controlled location.

Except that you should turn around the order here to retain backwards
compatibility: First check the unencrypted file, then the other three.
If you already have an unencrypted file, there is no reason not to use
it (it's cheaper), and existing setups would continue to work.

> Idea #2: We could change our usage of python-keyring so that if the
> GNOME Keyring and KDE Wallet are not available, the credential is
> written to an unencrypted file instead of an encrypted file. This would
> mean that GUI users get their credential encrypted, and console users
> don't.

This also will work from my POV, with the added benefit that you don't
need a separate script for the initial setup, but it's all built in.

> You would still have to run a cronjob script manually

Right, no way around that (but that's fine).

> , and use a console web browser to set up the credential.

That really shouldn't be necessary. If for some reason the usage of a
console web browser would now become required, that would certainly be
a step backwards. (See above).

So, I slightly prefer idea #2, as it's easier to use, but I'm fine
with either.

Thank you!

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu....

Read more...

Revision history for this message
Martin Pitt (pitti) wrote :

Gary Poster [2010-12-14 2:40 -0000]:
> AIUI, the big improvement between the old story and the new story is
> that, if someone were to steal your shut-down computer, they would not
> have easy access to your Launchpad authentication

There is an almost 100% chance that your browser is authenticated to
Launchpad. If for nothing else, then you would need to login in your
browser when authenticating the launchpadlib app. And by default the
LP login cookie lives forever.

If you want to protect your data against stealing your computer, you
have to encrypt your entire home directory (or entire disk).

So I don't see any significant security benefit here. It only helps
for the corner case that you never use Launchpad in the browser, and
logged out again after authenticating your launchpadlib app.

> Barring Kees or someone else making a strong argument that the increment
> of security improvements warrants breaking backwards compatibility, we
> have our direction: make things backwards compatible.

*happy* :-)

Thanks, Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)

Revision history for this message
Leonard Richardson (leonardr) wrote : Re: [Bug 686690] Re: 1.8.0 breaks login_with() API compat with existing credentials files, and forces keyrings

When we consciously broke backwards compatibility, we also believed that
> the smooth interaction of interactive applications--Ground Control,
> Hydrazine, Quickly--was important to encourage. We felt that perhaps
> the combination of the security and the automatic increase of usability
> of interactive applications was worth it.
>
> Again, it is a judgement call, and again, Francis has come down on the
> side of "no."
>
> Barring Kees or someone else making a strong argument that the increment
> of security improvements warrants breaking backwards compatibility, we
> have our direction: make things backwards compatible.

OK.

1. I would like to see an analysis of this situation from Kees, if for
no other reason than that a big part of our desktop integration pitch
was "Your desktop-wide credential will be stored in the GNOME Keyring,
not unencrypted on disk."

The idea was that 1) you'd gain protection from passive attacks, and 2)
you could gain *some* protection against active attacks by using a
keyring with a timeout. It's true that passive attacks are still
possible if your Launchpad cookie is stored unencrypted on disk, but
that's not an unalterable fact of life. if you're protective of your
Launchpad credentials, you can tell your browser not to store that
cookie between sessions.

The value of this is debatable--my browser session hasn't "ended" for a
year and a half because I've been saving open tabs. But the value of
setting up a separate keyring with timeout is also debatable, since
right now there is no GUI for giving a timeout to a keyring. The point
is that if you care a whole lot about the security of your credential,
you can take steps to secure it.

2. What counts as "backwards compatibility"? Do we still need to look
for credentials in
"~/.launchpadlib/api.edge.launchpad.net/credentials/Application name",
so that old credentials will still work? Do we still need to take a
credentials_file argument, so that different applications can keep their
individual "desktop-wide" credentials in totally random places? Or is it
enough to make cron scripts work again, once you install a new
(desktop-wide) credential in ~/.cache?

IMO we have done some good cleanup work and I don't want to see it all
put under the umbrella of "stuff we have to revert because we broke cron
scripts".

I am sympathetic to the idea that existing per-application credentials
should still work. It makes the code ugly, it saves existing users
trouble, it might cause those existing users confusion down the line. I
could go either way.

I would really like to get rid of the credentials_file argument. The
only reason I can think you'd need it is if you've got a single Unix
user running multiple cronjob scripts as different Launchpad users. If
that's the situation we have, then we should keep credentials_file for
now, and do some more work to support that scenario natively.

Revision history for this message
Leonard Richardson (leonardr) wrote :

> That would work mostly fine, I think. It would be great if
> login_with() can continue to support the credentials_file argument, so
> that you can put your auth file into a more controlled location.
>

I don't understand what you're doing. What makes one location on disk
more controlled than another?

Here's another thing I just realized: the desktop-wide credential is
associated with the name of the computer you used to create it. This is
just for informative purposes, but if you copy the credential to another
computer, that name will be inaccurate and it might get confusing. I
don't think this is a big deal.

Revision history for this message
Martin Pitt (pitti) wrote :

Hello Leonard,

Leonard Richardson [2010-12-14 14:15 -0000]:
> I don't understand what you're doing. What makes one location on disk
> more controlled than another?

What I do in the apport retracers is:

 - create a temporary chroot, and reconstruct the situation of the
   packages when the crash occurred
 - copy the auth file into /tmp/auth
 - call "apport-retrace --auth /tmp/auth" in the chroot

Without being able to specify the location of the credentials file,
I'd need to predict the path where launchpadlib will look for the
file, and put it there.

Revision history for this message
Leonard Richardson (leonardr) wrote :
Download full text (3.5 KiB)

I talked to Kees.

<kees> I think pitti's last comment is on-target: as long as there is _some_ way to do file-based credentials, that's fine.
<kees> I don't think you need to be strictly "backward compatible", though.
<leonardr> how bad would it be if we stopped using keyring and went back to a single unencrypted credential file?
<kees> it'd be kind of sad, given all the work put into making the keyring work. I don't think that code should be lost (why can't there be two ways to auth?)
<leonardr> in that case, do you agree with me that you should have to do something special to create an unecrypted credential file?
<leonardr> ie. it should never be created in normal usage, only by someone who knows that's what they're doing?
<kees> yeah, it's no worse that the current situation where you need a browser to create the cred file the first time. that would just change the process a little
<kees> as long as the cronjob use case is handled in some way, it's fine, IMO.

Here's my revised proposal:

1. launchpadlib looks for credentials in this order:

a) unencrypted in the path designated by credentials_file
b) unencryped in ~/.cache/launchpadlib/[host].credential
c) encrypted in the order determined by python-keyring

Alternative:
a) unencryped in ~/.cache/launchpadlib/[host].credential
b) encrypted in the order determined by python-keyring.

I would like to get rid of credentials_file because IMO its legitimate uses are outnumbered by its sketchy uses, but I'm OK with keeping it.

2. A script launchpadlib/bin/create_unencrypted_launchpad_credential lets you create a desktop-wide integration token for *any* computer name. If you want to run launchpadlib cronjobs on your computer, you run this script.

$ python create_unencrypted_launchpad_credential --instance production
[browser open]
I've written an unencrypted credential for "mycomputer" to "/home/leonardr/.cache/launchpadlib/api.launchpad.net.credential".
You can now run cronjobs that use launchpadlib.

If you want to run launchpadlib cronjobs on some other computer, you run this script and scp the credential over.

$ python create_unencrypted_launchpad_credential --instance production --hostname "myothercomputer" --output_file foreign.credential
[browser open]
I've written an unencrypted credential for "myothercomputer" to "foreign.credential".
If you want launchpadlib running on "myothercomputer" to pick up this credential automatically, scp this file to "~/.cache/launchpadlib/api.launchpad.net.credential".

$ scp foreign.credential myothercomputer:.cache/launchpadlib/api.launchpad.net.credential

Analysis:

1. If we keep credentials_file, your existing scripts that use credentials_file will continue to work.

2. If we eliminate credentials_file, you will need to know to copy the auth file into ~/.cache/launchpadlib/[host].credential instead of into /tmp/auth. But you can use your existing credential file.

3. Someone who is just starting out and wants to run cronjobs on their personal computer, can run create_unencrypted_launchpad_credential. Someone who wants to run cronjobs on some other computer can use create_unencrypted_launchpad_credential and scp the credential.

4. Do we forsee a f...

Read more...

Revision history for this message
Leonard Richardson (leonardr) wrote :

OK, I've talked to Gary. Here's my new proposal.

1. The existing login_with method will become the method of choice for scripts that are, or *might be*, run as cronjobs. This method will never access the keyring, even to check for cached credentials.

When you call login_with, launchpadlib looks for a desktop integration credential in ~/.cache/launchpadlib/[site].credential (or in the path designated by credentials_file). If a cached unencrypted credential is found, launchpadlib looks for a legacy application-specific credential in ~/.launchpadlib/cache/[site]/credential, and deletes it.

If no cached unencrypted credential is found, launchpadlib does a browser open asking for a desktop integration credential. The Launchpad URL also includes the query string value "show_unencrypted_warning=true". Because of this, the Launchpad page that asks you to authorize the token, also mentions that a credential will be stored unencrypted on your hard drive, allowing you to run applications from cron scripts.

Once the desktop integration credential is authorized, it's written unencrypted to ~/.cache/launchpadlib/[site].credential (or the path designated by credentials_file).

I don't have an opinion on what should happen if credentials_file designates a application-specific credential. Either the application-specific credential should be used, or a browser open should happen and credentials_file should be overwritten with a site-wide credential.

We can alias login_with to "login_without_user_input" or something, and encourage developers to migrate to the new name. This name is a bit of a misnomer, because if there is no credential you will still get a browser open. But

2. A new method will be created for applications that will never be run as a cronjob. I would like to call this method just plain "login", but we could call it "login_for_interactive" or something like that. This method will use the keyring exclusively, or almost exclusively.

login() does not recognize the credentials_file argument.

When you call login(), then maybe launchpadlib looks for a desktop integration credential in ~/.cache/launchpadlib/[site].credential, or maybe it doesn't. It doesn't matter much to me, but if there's an unencrypted credential lying around we might as well use it.

Either way, the next step is to ask python-keyring for a cached credential. (This may require user input to unlock the keyring.)

If a cached credential is found, login() looks for a legacy application-specific credential in ~/.launchpadlib/cache/[site]/credential, and deletes it, just like login_with() does.

If there is no cached credential, login() does a browser open, just like login_with() does. However, it does not put "show_unencrypted_warning=true" in the query string, so Launchpad doesn't give the warning about unencrypted storage.

Once the desktop integration credential is authorized, it's stored in the GNOME keyring (or python-keyring equivalent).

3. As soon as this is implemented, we'll go to the authors of Ground Control, Apport, etc. and help them port their code to use login() instead of login_with(). (Or whatever hacks they might have written instead of using login_with().

Revision history for this message
Gary Poster (gary) wrote :

Thank you. That looks good.

For clarity, I want to edit two paras. Edits are surrounded by asterisks (where one edit is the addition of an intervening paragraph.

"""
When you call login_with, launchpadlib looks for a desktop integration credential in ~/.cache/launchpadlib/[site].credential (or in the path designated by credentials_file). If a cached unencrypted *desktop-wide* credential is found, launchpadlib looks for a legacy application-specific credential in ~/.launchpadlib/cache/[site]/credential, and deletes it.

*If an unencrypted desktop integration credential is not found, launchpad looks for a legacy application-specific credential in the path designated by credentials_file, if given; and then in ~/.launchpadlib/cache/[site]/credential . If found, it is used.*

If no cached unencrypted credential is found *in any of the above locations*, launchpadlib does a browser open asking for a desktop integration credential. The Launchpad URL also includes the query string value "show_unencrypted_warning=true". Because of this, the Launchpad page that asks you to authorize the token, also mentions that a credential will be stored unencrypted on your hard drive, allowing you to run applications from cron scripts.
"""

My intervening paragraph above states my opinion on the answer to this issue: """I don't have an opinion on what should happen if credentials_file designates a application-specific credential. Either the application-specific credential should be used, or a browser open should happen and credentials_file should be overwritten with a site-wide credential.""" IOW, I think application-specific credentials should be used, for backwards compatibility.

A corollary for all of this is that I don't think the old per-application authorization code can ever go away entirely--we'll always need to be able to read them, even though we no longer write them.

I think the end of #1 ("But") was probably going to mention that the keyring might issue a challenge, and we never want that for non-interactive (cron-like) scripts.

Revision history for this message
Martin Pitt (pitti) wrote :

Thanks Leonard and Gary. This sounds fine to me.

If you want to discontinue support for the per-application credentials, we need to re-do all existing credentials files on our servers, but that's not a biggie. I'd really love you forever/buy you a beer if credentials_file could continue to work (especially as it's now more focussed on servers where you want to keep those files around forever), but if you really don't want to keep it, I can live with that.

> 1. The existing login_with method will become the method of choice for scripts ...

That already has been the case for a long time, for the record. I don't know a current project (ubuntu-dev-scripts, ubuntu-archive-tools, apport, langpack-o-matic, etc.) which doesn't use login_with(). :-)

Thanks for resolving this!

Revision history for this message
Leonard Richardson (leonardr) wrote :

Once I verify that the Launchpad test suite passes, I'll release launchpadlib trunk as version 1.9.0. Would you try this version out and see if it works for you?

You should still be able to use login_with() with a credentials file.

Revision history for this message
Martin Pitt (pitti) wrote : Re: [Bug 686690] Re: 1.8.0 breaks login_with() API compat with existing credentials files, and forces keyrings

Hello Leonard,

Leonard Richardson [2011-01-05 13:51 -0000]:
> Once I verify that the Launchpad test suite passes, I'll release
> launchpadlib trunk as version 1.9.0. Would you try this version out and
> see if it works for you?

Sure, I'm happy to test it.

Thanks a lot for your efforts here, and sorry for the trouble that
this caused.

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)

Revision history for this message
Robert Collins (lifeless) wrote :

One small niggle that occurs to me - we're putting credentials in
~/.cache now - I don't think folk are necessarily expecting
confidential files in .cache; would .config - where confidential files
*are* expected be better?

Revision history for this message
Martin Pitt (pitti) wrote :

Robert Collins [2011-01-05 19:50 -0000]:
> One small niggle that occurs to me - we're putting credentials in
> ~/.cache now - I don't think folk are necessarily expecting
> confidential files in .cache; would .config - where confidential files
> *are* expected be better?

To me the distinction has always been "small and precious" vs. "data
that I can always trash and don't need to backup", not a question of
confidentiality. I wouldn't ever publish my browser's cache directory
either -- I wouldn't be surprised if it had online banking pages or
shopping receipts, and the like.

If anything, I'd expect the contrary - configuration files are usually
harmless, and passwords etc. belong into the GNOME keyring.

This seems to be supported by the default permissions of these dirs:

 ls -ld .config .cache
drwx------ 31 martin martin 4096 2011-01-05 23:33 .cache
drwxr-xr-x 46 martin martin 12288 2011-01-03 13:23 .config

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)

Revision history for this message
Robert Collins (lifeless) wrote :

Ok, cool.

Revision history for this message
Leonard Richardson (leonardr) wrote :

I don't think this is a problem anymore. launchpadlib used to store unencrypted credential files in ~/.cache by default. But with this branch, if you want to store credentials unencrypted, you must specify the path they want. Credentials won't go into ~/.cache unless you tell launchpadlib to put them there.

Revision history for this message
Leonard Richardson (leonardr) wrote :

Martin, launchpadlib 1.9.0 (or 1.9.1) is ready for you to test. If you sign off on it I can try to get it put into Natty.

Revision history for this message
Launchpad QA Bot (lpqabot) wrote : Bug fixed by a commit
tags: added: qa-needstesting
Changed in launchpadlib:
status: Triaged → Fix Committed
Revision history for this message
Martin Pitt (pitti) wrote :

I tried the 1.9.0 release from Launchpad, but it just throws an exception:

$ lp-shell
Traceback (most recent call last):
  File "/usr/bin/lp-shell", line 57, in <module>
    lp = Launchpad.login_with('udt-lp-shell', instance, version=api_version)
  File "/usr/lib/python2.7/dist-packages/launchpadlib/launchpad.py", line 496, in login_with
    allow_access_levels)
  File "/usr/lib/python2.7/dist-packages/launchpadlib/launchpad.py", line 206, in authorization_engine_factory
    return AuthorizeRequestTokenWithBrowser(*args)
NameError: global name 'AuthorizeRequestTokenWithBrowser' is not defined

Please note that before we can upload 1.9.0 to natty, the python-keyring package needs to get updated and tested, and get a MIR approved.

Revision history for this message
Leonard Richardson (leonardr) wrote :

Great, the one LOC we still can't regression-test has a bug. Fortunately it's just a missing import.

This is easy to fix, but there's another problem. I don't think it's bad enough to scratch the whole project, and it might be considered a relatively minor bug in keyring. Let's talk it out.

Right now I can't run a launchpadlib script over an SSH session. I get this error when keyring tries to access the GNOME keyring on the foreign computer:

  File "/home/leonardr/canonical/lp-sourcedeps/eggs/keyring-0.5-py2.6.egg/keyring/backend.py", line 139, in get_password
    items = gnomekeyring.find_network_password_sync(username, service)
gnomekeyring.IOError

That makes sense--no reason why I should be able to SSH into another machine and dump the keyring--but it prevents Launchpad.login_with() from working at all.

I would like to be able to tell keyring to fall back to an encrypted file instead of crashing in this situation. But I don't know if this is the right thing to do in general.

Revision history for this message
Leonard Richardson (leonardr) wrote :

I should mention that if I pass in a credentials_file to login_with(), then that works--the whole keyring code is bypassed.

Revision history for this message
Leonard Richardson (leonardr) wrote :

I was able to get the keyring to work over a remote X session by running "export `dbus-launch`". IMO this is a good enough workaround--I'll be putting it in my .bashrc, and we can mention it in the documentation. So I think we can proceed as planned.

Revision history for this message
Leonard Richardson (leonardr) wrote :

Martin, try launchpadlib 1.9.2. It's not in Launchpad yet, but it is released.

Revision history for this message
Martin Pitt (pitti) wrote :

With 1.9.2 I confirm that applications using "credentials_file" still work as before (apport), so the first half of the bug is solved with that.

The second half ("forces usage of keyrings and passwords") is still unchanged. Existing credentials from applications which don't use credentials_file (e. g. lp-shell, and just about every other tool in ubuntu-dev-scripts, ubuntu-archive-tools, etc.) now don't use the existing credentials file any more, and instead prompt you for a new authentication; that bit is probably intended as a long-term migration strategy, I can live with that. But forcing a password and keyring is really pretty inconvenient and also unnecessary (see discussion above), especially as it could at least use the GNOME keyring instead of the prompting on the command line.

Thanks!

Revision history for this message
Martin Pool (mbp) wrote : Re: [Bug 686690] Re: 1.8.0 breaks login_with() API compat with existing credentials files, and forces keyrings

On 7 January 2011 10:25, Leonard Richardson
<email address hidden> wrote:
> Great, the one LOC we still can't regression-test has a bug. Fortunately
> it's just a missing import.
>
> This is easy to fix, but there's another problem. I don't think it's bad
> enough to scratch the whole project, and it might be considered a
> relatively minor bug in keyring. Let's talk it out.
>
> Right now I can't run a launchpadlib script over an SSH session. I get
> this error when keyring tries to access the GNOME keyring on the foreign
> computer:
>
>  File "/home/leonardr/canonical/lp-sourcedeps/eggs/keyring-0.5-py2.6.egg/keyring/backend.py", line 139, in get_password
>    items = gnomekeyring.find_network_password_sync(username, service)
> gnomekeyring.IOError
>
> That makes sense--no reason why I should be able to SSH into another
> machine and dump the keyring--but it prevents Launchpad.login_with()
> from working at all.
>
> I would like to be able to tell keyring to fall back to an encrypted
> file instead of crashing in this situation. But I don't know if this is
> the right thing to do in general.

Just catch the gnomekeyring.IOError and assume it means there is no keyring

Revision history for this message
Leonard Richardson (leonardr) wrote :

We've started ignoring unencrypted-credentials-on-disk because we want people to get a single new desktop-wide credential. We made the keyring change at the same time so as not to create another discontinuity later.

"it could at least use the GNOME keyring instead of the prompting on the command line."

You should only get the command line prompt if neither the GNOME keyring nor the KDE Wallet is active. (This is controlled by python-keyring.) What does your environment look like?

Benji, do you know why this might happen?

"Just catch the gnomekeyring.IOError and assume it means there is no keyring"

Assuming this is the right thing to do, it would have to be done inside the keyring module, which is why I speculated that we might treat this as a bug in python-keyring. Fortunately there's an easy workaround, so I'm not worried about it.

Benji York (benji)
Changed in launchpadlib:
assignee: Benji York (benji) → Leonard Richardson (leonardr)
Revision history for this message
Benji York (benji) wrote :

On Sun, Jan 9, 2011 at 5:49 PM, Martin Pool <email address hidden> wrote:
> Just catch the gnomekeyring.IOError and assume it means there is no
> keyring

Unfortunately it's not that easy. The keyring package chooses the back
end (GNOME keyring in this case) early and doesn't have a mechanism to
fall back to another back end if the chosen one doesn't end up working.

Oh, I just realized you may be suggesting that launchpadlib (as opposed
to keyring) catch the exception. Yep, that would be a reasonable
workaround.
--
Benji York

Revision history for this message
Martin Pitt (pitti) wrote :

Leonard Richardson [2011-01-10 14:03 -0000]:
> You should only get the command line prompt if neither the GNOME keyring
> nor the KDE Wallet is active. (This is controlled by python-keyring.)
>
> What does your environment look like?

Standard GNOME session. I suppose it's because python-keyring package
is still at version 0.2, and I believe you were using 0.5?

Revision history for this message
Benji York (benji) wrote :

On Mon, Jan 10, 2011 at 9:03 AM, Leonard Richardson
<email address hidden> wrote:
> "it could at least use the GNOME keyring instead of the prompting on the
> command line."
>
> You should only get the command line prompt if neither the GNOME keyring
> nor the KDE Wallet is active. (This is controlled by python-keyring.)
> What does your environment look like?
>
> Benji, do you know why this might happen?

Nope, I'm not aware of a situation in which both a real keyring/wallet
backend is used and you still get a command line prompt.
--
Benji York

Revision history for this message
Martin Pool (mbp) wrote :

Yes, that's what I meant. If python-keyring chooses a non working keyring,
just don't use it at all.

- Martin
On 10/01/2011 9:01 AM, "Benji York" <email address hidden> wrote:
> On Sun, Jan 9, 2011 at 5:49 PM, Martin Pool <email address hidden> wrote:
>> Just catch the gnomekeyring.IOError and assume it means there is no
>> keyring
>
> Unfortunately it's not that easy. The keyring package chooses the back
> end (GNOME keyring in this case) early and doesn't have a mechanism to
> fall back to another back end if the chosen one doesn't end up working.
>
> Oh, I just realized you may be suggesting that launchpadlib (as opposed
> to keyring) catch the exception. Yep, that would be a reasonable
> workaround.
> --
> Benji York
>
> --
> You received this bug notification because you are subscribed to
> launchpadlib .
> https://bugs.launchpad.net/bugs/686690
>
> Title:
> 1.8.0 breaks login_with() API compat with existing credentials files, and
forces keyrings
>

j.c.sackett (jcsackett)
tags: added: qa-ok
removed: qa-needstesting
Changed in launchpadlib:
status: Fix Committed → Fix Released
Revision history for this message
Martin Pool (mbp) wrote :

There's some fallout in bug 752282, and I was rereading this bug, and saw

> 2. A new method will be created for applications that will never be run as a cronjob. I would like to call this method just plain "login", but we could call it "login_for_interactive" or something like that. This method will use the keyring exclusively, or almost exclusively.

It looks like this has not been done in trunk; please don't do it. I can't think of a realistic case where an application would prefer to fail if it's not running on a desktop with a working keyring. I can see how some _users_ would want to never have unencrypted tokens on disk, but as pitti discussed above, those people are far better off just encrypting their disk, and they are very likely already doing so.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.