10637.3.1
by Guilherme Salgado
Use the default python version instead of a hard-coded version |
1 |
#!/usr/bin/python -S
|
8452.3.3
by Karl Fogel
* utilities/: Add copyright header block to source files that were |
2 |
#
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
3 |
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
|
8687.15.3
by Karl Fogel
Shorten the copyright header block to two lines. |
4 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
8452.3.3
by Karl Fogel
* utilities/: Add copyright header block to source files that were |
5 |
|
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
6 |
"""Create a user for testing the local Launchpad.
|
7 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
8 |
Usage: make-lp-user <username> [<team1> <team2> ...] [-e email]
|
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
9 |
|
10 |
This script will create a usable Launchpad user in the development database to
|
|
11 |
help you test a locally running copy of Launchpad.
|
|
12 |
||
13 |
You can add this user to teams by specifying them on the command-line. For
|
|
14 |
example:
|
|
15 |
||
16 |
make-lp-user fred vcs-imports bazaar-experts
|
|
17 |
||
18 |
will create a user 'fred' and add them to the 'vcs-imports' and
|
|
19 |
'bazaar-experts' teams.
|
|
20 |
||
21 |
In addition, this script will look in your ~/.ssh directory for public keys
|
|
22 |
and register them for the created user.
|
|
23 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
24 |
If you pass an email address, the new user will have this email address
|
25 |
as well as any GPG keys you have for it.
|
|
26 |
||
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
27 |
The login details will be printed to stdout.
|
28 |
||
29 |
Please note that this script is for testing purposes only. Do NOT use it in
|
|
30 |
production environments.
|
|
31 |
"""
|
|
32 |
||
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
33 |
import _pythonpath |
34 |
||
35 |
import os |
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
36 |
from optparse import OptionParser |
37 |
import re |
|
38 |
import subprocess |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
39 |
import sys |
40 |
import transaction |
|
41 |
||
10427.4.6
by Jeroen Vermeulen
Final polish. I hope. |
42 |
from storm.store import Store |
43 |
||
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
44 |
from zope.component import getUtility |
45 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
46 |
from canonical.launchpad.interfaces.gpghandler import IGPGHandler |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
47 |
from canonical.launchpad.scripts import execute_zcml_for_scripts |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
48 |
from lp.registry.interfaces.gpg import GPGKeyAlgorithm, IGPGKeySet |
11882.2.2
by Jonathan Lange
Clear up a heck of a lot of imports from canonical.launchpad.interfaces. |
49 |
from lp.registry.interfaces.person import IPersonSet |
50 |
from lp.registry.interfaces.ssh import ISSHKeySet |
|
51 |
from lp.registry.interfaces.teammembership import TeamMembershipStatus |
|
8440.1.1
by Curtis Hovey
Updated all imports or LaunchpadObjectFactory to come from lp.test.factory. |
52 |
from lp.testing.factory import LaunchpadObjectFactory |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
53 |
|
54 |
# Shut up, pyflakes.
|
|
55 |
_pythonpath = _pythonpath |
|
56 |
||
57 |
||
58 |
DEFAULT_PASSWORD = 'test' |
|
59 |
factory = LaunchpadObjectFactory() |
|
60 |
||
61 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
62 |
def make_person(username, email): |
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
63 |
"""Create and return a person with the given username.
|
64 |
||
65 |
The email address for the user will be <username>@example.com. The
|
|
66 |
password will be the value of `DEFAULT_PASSWORD`.
|
|
67 |
||
68 |
These details will be printed to stdout.
|
|
69 |
"""
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
70 |
person = factory.makePerson( |
71 |
name=username, password=DEFAULT_PASSWORD, email=email) |
|
72 |
print "username: %s" % (username,) |
|
73 |
print "email: %s" % (email,) |
|
74 |
print "password: %s" % (DEFAULT_PASSWORD,) |
|
75 |
return person |
|
76 |
||
77 |
||
78 |
def add_person_to_teams(person, team_names): |
|
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
79 |
"""Add `person` to the teams named in `team_names`.
|
80 |
||
81 |
`person` is provided as its own review, team membership status is always
|
|
82 |
`APPROVED`. This function will add users even to restricted teams.
|
|
83 |
||
84 |
A list of teams joined will be printed to stdout.
|
|
85 |
"""
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
86 |
person_set = getUtility(IPersonSet) |
6488.1.4
by Jonathan Lange
Slightly more error handling. |
87 |
teams_joined = [] |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
88 |
for team_name in team_names: |
89 |
team = person_set.getByName(team_name) |
|
6488.1.4
by Jonathan Lange
Slightly more error handling. |
90 |
if team is None: |
91 |
print "ERROR: %s not found." % (team_name,) |
|
92 |
continue
|
|
93 |
if not team.is_team: |
|
94 |
print "ERROR: %s is not a team." % (team_name,) |
|
95 |
continue
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
96 |
team.addMember( |
97 |
person, person, status=TeamMembershipStatus.APPROVED) |
|
6488.1.4
by Jonathan Lange
Slightly more error handling. |
98 |
teams_joined.append(team_name) |
99 |
print "teams: %s" % ' '.join(teams_joined) |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
100 |
|
101 |
||
102 |
def add_ssh_public_keys(person): |
|
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
103 |
"""Look for public keys and register them for `person`.
|
104 |
||
105 |
This function looks in ~/.ssh/id_rsa.pub and ~/.ssh/id_dsa.pub for SSH
|
|
106 |
public keys and registers them as SSH keys for `person`.
|
|
107 |
"""
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
108 |
ssh_dir = os.path.expanduser('~/.ssh') |
109 |
key_set = getUtility(ISSHKeySet) |
|
11332.1.1
by Steve Kowalik
Change how SSH keys are added in utilities/make-lp-user, no longer guess the |
110 |
for filename in ('id_rsa.pub', 'id_dsa.pub'): |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
111 |
try: |
11435.8.1
by Ian Booth
Use proper file name when reading SSH keys, print message when none found |
112 |
public_key_file = open(os.path.join(ssh_dir, filename), 'r') |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
113 |
try: |
114 |
public_key = public_key_file.read() |
|
115 |
finally: |
|
116 |
public_key_file.close() |
|
117 |
except (OSError, IOError): |
|
118 |
continue
|
|
11332.1.1
by Steve Kowalik
Change how SSH keys are added in utilities/make-lp-user, no longer guess the |
119 |
key_set.new(person, public_key) |
120 |
print 'Registered SSH key: %s' % (filename,) |
|
11435.8.1
by Ian Booth
Use proper file name when reading SSH keys, print message when none found |
121 |
break
|
122 |
else: |
|
123 |
print 'No SSH key files found in %s' % ssh_dir |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
124 |
|
125 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
126 |
def parse_fingerprints(gpg_output): |
127 |
"""Find key fingerprints in "gpg --fingerprint <email>" output."""
|
|
128 |
line_prefix = re.compile('\s*Key fingerprint\s*=\s*') |
|
129 |
return [ |
|
130 |
''.join(re.sub(line_prefix, '', line).split()) |
|
131 |
for line in gpg_output.splitlines() |
|
132 |
if line_prefix.match(line) |
|
133 |
]
|
|
134 |
||
135 |
||
136 |
def run_native_gpg(arguments): |
|
137 |
"""Run GPG using the user's real keyring."""
|
|
138 |
# Need to override GNUPGHOME or we'll get a dummy GPG in a temp
|
|
139 |
# directory, which won't find any keys.
|
|
140 |
env = os.environ.copy() |
|
141 |
if 'GNUPGHOME' in env: |
|
142 |
del env['GNUPGHOME'] |
|
10427.4.8
by Jeroen Vermeulen
Beware of translated gpg, thanks adeuring for spotting that. |
143 |
|
144 |
# Prevent translated gpg output from messing up our parsing.
|
|
145 |
env['LC_ALL'] = 'C' |
|
146 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
147 |
command_line = ['gpg'] + arguments |
148 |
pipe = subprocess.Popen( |
|
149 |
command_line, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
150 |
stdout, stderr = pipe.communicate() |
|
151 |
if stderr != '': |
|
152 |
print stderr |
|
153 |
if pipe.returncode != 0: |
|
154 |
raise Exception('GPG error during "%s"' % ' '.join(command_line)) |
|
155 |
||
156 |
return stdout |
|
157 |
||
158 |
||
159 |
def add_gpg_key(person, fingerprint): |
|
160 |
"""Add the GPG key with the given fingerprint to `person`."""
|
|
161 |
run_native_gpg([ |
|
162 |
'--keyserver', 'keyserver.launchpad.dev', |
|
163 |
'--send-key', fingerprint |
|
164 |
])
|
|
165 |
||
166 |
gpghandler = getUtility(IGPGHandler) |
|
167 |
key = gpghandler.retrieveKey(fingerprint) |
|
168 |
||
169 |
gpgkeyset = getUtility(IGPGKeySet) |
|
170 |
if gpgkeyset.getByFingerprint(fingerprint) is not None: |
|
171 |
# We already have this key.
|
|
172 |
return
|
|
173 |
||
174 |
algorithm = GPGKeyAlgorithm.items[key.algorithm] |
|
175 |
can_encrypt = True |
|
176 |
lpkey = gpgkeyset.new( |
|
177 |
person.id, key.keyid, fingerprint, key.keysize, algorithm, |
|
178 |
active=True, can_encrypt=can_encrypt) |
|
179 |
Store.of(person).add(lpkey) |
|
180 |
||
181 |
||
182 |
def attach_gpg_keys(email, person): |
|
183 |
"""Attach the GPG key(s) for `email` to `person`."""
|
|
184 |
output = run_native_gpg(['--fingerprint', email]) |
|
185 |
||
186 |
fingerprints = parse_fingerprints(output) |
|
187 |
if len(fingerprints) == 0: |
|
188 |
print "No GPG key fingerprints found!" |
|
189 |
for fingerprint in fingerprints: |
|
190 |
add_gpg_key(person, fingerprint) |
|
191 |
||
192 |
||
193 |
def parse_args(arguments): |
|
194 |
"""Parse command-line arguments.
|
|
195 |
||
196 |
:return: options object. Among the options are username (a
|
|
197 |
string) and optionally teams (a list).
|
|
198 |
"""
|
|
199 |
parser = OptionParser(description="Create a local Launchpad user.") |
|
200 |
parser.add_option( |
|
201 |
'-e', '--email', action='store', dest='email', default=None, |
|
202 |
help="Email address; set to use real GPG key for this address.") |
|
10427.4.4
by Jeroen Vermeulen
Better options processing. |
203 |
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
204 |
options, args = parser.parse_args(arguments) |
205 |
if len(args) == 0: |
|
206 |
print __doc__ |
|
10427.4.4
by Jeroen Vermeulen
Better options processing. |
207 |
sys.exit(2) |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
208 |
|
209 |
options.username = args[0] |
|
210 |
options.teams = args[1:] |
|
211 |
||
212 |
return options |
|
213 |
||
214 |
||
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
215 |
def main(arguments): |
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
216 |
"""Run the script."""
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
217 |
options = parse_args(arguments) |
218 |
if options.email is None: |
|
219 |
email = '%s@example.com' % options.username |
|
220 |
else: |
|
221 |
email = options.email |
|
222 |
||
10427.4.4
by Jeroen Vermeulen
Better options processing. |
223 |
execute_zcml_for_scripts() |
224 |
transaction.begin() |
|
225 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
226 |
person = make_person(options.username, email) |
227 |
add_person_to_teams(person, options.teams) |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
228 |
add_ssh_public_keys(person) |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
229 |
|
230 |
if options.email is not None: |
|
231 |
attach_gpg_keys(options.email, person) |
|
232 |
||
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
233 |
transaction.commit() |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
234 |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
235 |
return 0 |
236 |
||
237 |
||
238 |
if __name__ == '__main__': |
|
239 |
sys.exit(main(sys.argv[1:])) |