Merge lp:~sil/desktopcouch/create-oauth-tokens-startup into lp:desktopcouch

Proposed by Stuart Langridge
Status: Rejected
Rejected by: Elliot Murphy
Proposed branch: lp:~sil/desktopcouch/create-oauth-tokens-startup
Merge into: lp:desktopcouch
Diff against target: None lines
To merge this branch: bzr merge lp:~sil/desktopcouch/create-oauth-tokens-startup
Reviewer Review Type Date Requested Status
Mark G. Saye (community) Needs Fixing
Elliot Murphy (community) Needs Fixing
Joshua Blount (community) Approve
Review via email: mp+10481@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Stuart Langridge (sil) wrote :

Add oauth tokens as part of initial desktopcouch setup, and lock desktopcouch access to authenticated users only.

(NB: do not merge into desktopcouch trunk until http://issues.apache.org/jira/browse/COUCHDB-478 is in your couchdb build, or this will prevent access to your desktop Couch; it sets up an admin user in the ini file, but oauth authentication doesn't read from the ini file in Couch trunk; that's what the above patch is for.)

Revision history for this message
Joshua Blount (jblount) :
review: Approve
Revision history for this message
Elliot Murphy (statik) wrote :

I've packaged 0.10.0~svn806985~ppa1, which is a snapshot of the 0.10 branch that Jan created today, + the part of the patch for COUCHDB-478 that has not been applied to the branch yet.

After merging with trunk and resolving the merge conflicts, I get errors on a number of tests, all appear to have the same cause: 401 on a HEAD request.

===============================================================================
[ERROR]: desktopcouch.records.tests.test_server.TestCouchDatabase.test_record_exists

Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/testtools/testcase.py", line 161, in run
    self.setUp()
  File "/home/emurphy/canonical/ubuntuone/shared/desktopcouch/trunk/desktopcouch/records/tests/test_server.py", line 44, in setUp
    self.dbname, create=True, uri=URI)
  File "/home/emurphy/canonical/ubuntuone/shared/desktopcouch/trunk/desktopcouch/records/server.py", line 58, in __init__
    if database not in self._server:
  File "/usr/lib/pymodules/python2.6/couchdb/client.py", line 124, in __contains__
    self.resource.head(validate_dbname(name))
  File "/usr/lib/pymodules/python2.6/couchdb/client.py", line 981, in head
    return self._request('HEAD', path, headers=headers, **params)
  File "/usr/lib/pymodules/python2.6/couchdb/client.py", line 1035, in _request
    raise ServerError((status_code, error))
couchdb.client.ServerError: (401, '')
===============================================================================
[ERROR]: desktopcouch.records.tests.test_server.TestCouchDatabase.test_update_fields

Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/testtools/testcase.py", line 161, in run
    self.setUp()
  File "/home/emurphy/canonical/ubuntuone/shared/desktopcouch/trunk/desktopcouch/records/tests/test_server.py", line 44, in setUp
    self.dbname, create=True, uri=URI)
  File "/home/emurphy/canonical/ubuntuone/shared/desktopcouch/trunk/desktopcouch/records/server.py", line 58, in __init__
    if database not in self._server:
  File "/usr/lib/pymodules/python2.6/couchdb/client.py", line 124, in __contains__
    self.resource.head(validate_dbname(name))
  File "/usr/lib/pymodules/python2.6/couchdb/client.py", line 981, in head
    return self._request('HEAD', path, headers=headers, **params)
  File "/usr/lib/pymodules/python2.6/couchdb/client.py", line 1035, in _request
    raise ServerError((status_code, error))
couchdb.client.ServerError: (401, '')

review: Needs Fixing
Revision history for this message
Stuart Langridge (sil) wrote :

> I've packaged 0.10.0~svn806985~ppa1, which is a snapshot of the 0.10 branch
> that Jan created today, + the part of the patch for COUCHDB-478 that has not
> been applied to the branch yet.
>
> After merging with trunk and resolving the merge conflicts, I get errors on a
> number of tests, all appear to have the same cause: 401 on a HEAD request.

Yep. This is a COuch bug (http://issues.apache.org/jira/browse/COUCHDB-479) the fix for which has not yet been merged into trunk :-(

Revision history for this message
Stuart Langridge (sil) wrote :

> > I've packaged 0.10.0~svn806985~ppa1, which is a snapshot of the 0.10 branch
> > that Jan created today, + the part of the patch for COUCHDB-478 that has not
> > been applied to the branch yet.
> >
> > After merging with trunk and resolving the merge conflicts, I get errors on
> a
> > number of tests, all appear to have the same cause: 401 on a HEAD request.
>
> Yep. This is a COuch bug (http://issues.apache.org/jira/browse/COUCHDB-479)
> the fix for which has not yet been merged into trunk :-(

Ah, it may have been merged now, looking at the bug report, but I don't know if it's in our packages yet...

Revision history for this message
Mark G. Saye (markgsaye) wrote :
Download full text (5.6 KiB)

> bzr merge lp:~sil/desktopcouch/create-oauth-tokens-startup
 M data/couchdb.tmpl
 M desktopcouch/start_local_couchdb.py
Text conflict in desktopcouch/start_local_couchdb.py
1 conflicts encountered.

> bzr diff desktopcouch/start_local_couchdb.py
=== modified file 'desktopcouch/start_local_couchdb.py'
--- desktopcouch/start_local_couchdb.py 2009-08-21 22:45:24 +0000
+++ desktopcouch/start_local_couchdb.py 2009-08-24 11:12:48 +0000
@@ -34,14 +34,16 @@
 """

 from __future__ import with_statement
-import os, subprocess, sys, glob
+import os, subprocess, sys, glob, random, string
 import desktopcouch
 from desktopcouch import local_files
 import xdg.BaseDirectory
 import errno
-import time
+import time, gtk, gnomekeyring
 from desktopcouch.records.server import CouchDatabase

+ACCEPTABLE_USERNAME_PASSWORD_CHARS = string.lowercase + string.uppercase
+
 def dump_ini(data, filename):
     """Dump INI data with sorted sections and keywords"""
     fd = open(filename, 'w')
@@ -60,9 +62,38 @@
         ini_path=local_files.FILE_INI, db_dir=local_files.DIR_DB,
         log_path=local_files.FILE_LOG, port="0"):
     """Write CouchDB ini file if not already present"""
+<<<<<<< TREE
     if os.path.exists(ini_path):
         return
     ini = {
+=======
+ if os.path.exists(local_files.FILE_INI):
+ # load the username and password from the keyring
+ try:
+ data = gnomekeyring.find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET,
+ {'desktopcouch': 'basic'})
+ except gnomekeyring.NoMatchError:
+ data = None
+ if data:
+ username, password = data[0].secret.split(":")
+ return username, password
+ # otherwise fall through; for some reason the access details aren't
+ # in the keyring, so re-create the ini file and do it all again
+
+ # randomly generate tokens and usernames
+ def make_random_string(count):
+ return ''.join([random.choice(ACCEPTABLE_USERNAME_PASSWORD_CHARS)
+ for x in range(count)])
+
+ ADMIN_ACCOUNT_USERNAME = make_random_string(10)
+ ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD = make_random_string(10)
+ CONSUMER_KEY = make_random_string(10)
+ CONSUMER_SECRET = make_random_string(10)
+ TOKEN = make_random_string(10)
+ TOKEN_SECRET = make_random_string(10)
+
+ local = {
+>>>>>>> MERGE-SOURCE
         'couchdb': {
             'database_dir': db_dir,
             'view_index_dir': db_dir,
@@ -75,10 +106,51 @@
             'file': log_path,
             'level': 'info',
         },
+ 'admins': {
+ ADMIN_ACCOUNT_USERNAME: ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD
+ },
+ 'oauth_consumer_secrets': {
+ CONSUMER_KEY: CONSUMER_SECRET
+ },
+ 'oauth_token_secrets': {
+ TOKEN: TOKEN_SECRET
+ },
+ 'oauth_token_users': {
+ TOKEN: ADMIN_ACCOUNT_USERNAME
+ },
+ 'couch_httpd_auth': {
+ 'require_valid_user': 'true'
+ }
     }
+<<<<<<< TREE
     dump...

Read more...

review: Needs Fixing
Revision history for this message
Elliot Murphy (statik) wrote :

> Ah, it may have been merged now, looking at the bug report, but I don't know
> if it's in our packages yet...

Yep, I made sure that the commit which included the purported fix for COUCHDB-479 was included in the couchdb snapshot, but looks like the fix for COUCHDB-479 was broken. We're waiting for couchdb devs to give us a working fix.

Revision history for this message
Elliot Murphy (statik) wrote :

rejecting this branch, and merging thisfreds noauth, which combines everything as we discussed this morning.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/couchdb.tmpl'
2--- data/couchdb.tmpl 2009-07-14 13:53:21 +0000
3+++ data/couchdb.tmpl 2009-08-20 12:55:54 +0000
4@@ -31,7 +31,7 @@
5 come back to browse your CouchDB again.</p>
6 <p>Don't bookmark the CouchDB page itself, because its location may change!</p>
7 <p>Taking you to your Desktop CouchDB in <span>30</span> seconds...
8-<a id="there" href="http://localhost:[[COUCHDB_PORT]]/_utils">take me
9+<a id="there" href="http://[[COUCHDB_USERNAME]]:[[COUCHDB_PASSWORD]]@localhost:[[COUCHDB_PORT]]/_utils">take me
10 there straight away from now on</a> (remember to bookmark this page first!)</p>
11 </body>
12 </html>
13
14=== modified file 'desktopcouch/start_local_couchdb.py'
15--- desktopcouch/start_local_couchdb.py 2009-08-19 16:00:01 +0000
16+++ desktopcouch/start_local_couchdb.py 2009-08-20 12:55:54 +0000
17@@ -32,14 +32,16 @@
18 """
19
20 from __future__ import with_statement
21-import os, subprocess, sys, glob
22+import os, subprocess, sys, glob, random, string
23 import desktopcouch
24 from desktopcouch import local_files
25 import xdg.BaseDirectory
26 import errno
27-import time
28+import time, gtk, gnomekeyring
29 from desktopcouch.records.server import CouchDatabase
30
31+ACCEPTABLE_USERNAME_PASSWORD_CHARS = string.lowercase + string.uppercase
32+
33 def dump_ini(data, filename):
34 """Dump INI data with sorted sections and keywords"""
35 fd = open(filename, 'w')
36@@ -56,18 +58,31 @@
37
38 def create_ini_file():
39 """Write CouchDB ini file if not already present"""
40- # FIXME add update trigger folder
41- #update_trigger_dir = [
42- # 'lib', 'canonical', 'ubuntuone', 'cloud_server', 'update_triggers']
43- #
44- #timestamp_trigger = os.path.join(
45- # *update_trigger_dir + ['timestamp_trigger.py'])
46- #update_trigger = os.path.join(
47- # *update_trigger_dir + ['update_trigger.py'])
48-
49 if os.path.exists(local_files.FILE_INI):
50- return
51-
52+ # load the username and password from the keyring
53+ try:
54+ data = gnomekeyring.find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET,
55+ {'desktopcouch': 'basic'})
56+ except gnomekeyring.NoMatchError:
57+ data = None
58+ if data:
59+ username, password = data[0].secret.split(":")
60+ return username, password
61+ # otherwise fall through; for some reason the access details aren't
62+ # in the keyring, so re-create the ini file and do it all again
63+
64+ # randomly generate tokens and usernames
65+ def make_random_string(count):
66+ return ''.join([random.choice(ACCEPTABLE_USERNAME_PASSWORD_CHARS)
67+ for x in range(count)])
68+
69+ ADMIN_ACCOUNT_USERNAME = make_random_string(10)
70+ ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD = make_random_string(10)
71+ CONSUMER_KEY = make_random_string(10)
72+ CONSUMER_SECRET = make_random_string(10)
73+ TOKEN = make_random_string(10)
74+ TOKEN_SECRET = make_random_string(10)
75+
76 local = {
77 'couchdb': {
78 'database_dir': local_files.DIR_DB,
79@@ -81,9 +96,43 @@
80 'file': local_files.FILE_LOG,
81 'level': 'info',
82 },
83+ 'admins': {
84+ ADMIN_ACCOUNT_USERNAME: ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD
85+ },
86+ 'oauth_consumer_secrets': {
87+ CONSUMER_KEY: CONSUMER_SECRET
88+ },
89+ 'oauth_token_secrets': {
90+ TOKEN: TOKEN_SECRET
91+ },
92+ 'oauth_token_users': {
93+ TOKEN: ADMIN_ACCOUNT_USERNAME
94+ },
95+ 'couch_httpd_auth': {
96+ 'require_valid_user': 'true'
97+ }
98 }
99
100 dump_ini(local, local_files.FILE_INI)
101+ # save admin account details in keyring
102+ item_id = gnomekeyring.item_create_sync(
103+ None,
104+ gnomekeyring.ITEM_GENERIC_SECRET,
105+ 'Desktop Couch user authentication',
106+ {'desktopcouch': 'basic'},
107+ "%s:%s" % (ADMIN_ACCOUNT_USERNAME, ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD),
108+ True)
109+ # and oauth tokens
110+ item_id = gnomekeyring.item_create_sync(
111+ None,
112+ gnomekeyring.ITEM_GENERIC_SECRET,
113+ 'Desktop Couch user authentication',
114+ {'desktopcouch': 'oauth'},
115+ "%s:%s:%s:%s" % (CONSUMER_KEY, CONSUMER_SECRET, TOKEN, TOKEN_SECRET),
116+ True)
117+
118+
119+ return (ADMIN_ACCOUNT_USERNAME, ADMIN_ACCOUNT_BASIC_AUTH_PASSWORD)
120
121 def run_couchdb():
122 """Actually start the CouchDB process"""
123@@ -146,7 +195,7 @@
124 # than inefficiently just overwriting it regardless
125 db.add_view(view_name, mapjs, reducejs, dd_name)
126
127-def write_bookmark_file():
128+def write_bookmark_file(username, password):
129 """Write out an HTML document that the user can bookmark to find their DB"""
130 bookmark_file = os.path.join(local_files.DIR_DB, "couchdb.html")
131
132@@ -182,21 +231,24 @@
133 pass
134 else:
135 fp = open(bookmark_file, "w")
136- fp.write(html.replace("[[COUCHDB_PORT]]", port))
137+ out = html.replace("[[COUCHDB_PORT]]", port)
138+ out = out.replace("[[COUCHDB_USERNAME]]", username)
139+ out = out.replace("[[COUCHDB_PASSWORD]]", password)
140+ fp.write(out)
141 fp.close()
142 print "Browse your desktop CouchDB at file://%s" % \
143 os.path.realpath(bookmark_file)
144
145 def start_couchdb():
146 """Execute each step to start a desktop CouchDB"""
147- create_ini_file()
148+ username, password = create_ini_file()
149 run_couchdb()
150 # Note that we do not call update_design_documents here. This is because
151 # Couch won't actually have started yet, so when update_design_documents
152 # calls the Records API, that will call back into get_pid and we end up
153 # starting Couch again. Instead, get_pid calls update_design_documents
154 # *after* Couch startup has occurred.
155- write_bookmark_file()
156+ write_bookmark_file(username, password)
157
158
159 if __name__ == "__main__":

Subscribers

People subscribed via source and target branches