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 |
||
46 |
from canonical.launchpad.interfaces import ( |
|
47 |
IPersonSet, |
|
48 |
ISSHKeySet, |
|
49 |
TeamMembershipStatus, |
|
50 |
)
|
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
51 |
from canonical.launchpad.interfaces.gpghandler import IGPGHandler |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
52 |
from canonical.launchpad.scripts import execute_zcml_for_scripts |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
53 |
from lp.registry.interfaces.gpg import GPGKeyAlgorithm, IGPGKeySet |
8440.1.1
by Curtis Hovey
Updated all imports or LaunchpadObjectFactory to come from lp.test.factory. |
54 |
from lp.testing.factory import LaunchpadObjectFactory |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
55 |
|
56 |
# Shut up, pyflakes.
|
|
57 |
_pythonpath = _pythonpath |
|
58 |
||
59 |
||
60 |
DEFAULT_PASSWORD = 'test' |
|
61 |
factory = LaunchpadObjectFactory() |
|
62 |
||
63 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
64 |
def make_person(username, email): |
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
65 |
"""Create and return a person with the given username.
|
66 |
||
67 |
The email address for the user will be <username>@example.com. The
|
|
68 |
password will be the value of `DEFAULT_PASSWORD`.
|
|
69 |
||
70 |
These details will be printed to stdout.
|
|
71 |
"""
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
72 |
person = factory.makePerson( |
73 |
name=username, password=DEFAULT_PASSWORD, email=email) |
|
74 |
print "username: %s" % (username,) |
|
75 |
print "email: %s" % (email,) |
|
76 |
print "password: %s" % (DEFAULT_PASSWORD,) |
|
77 |
return person |
|
78 |
||
79 |
||
80 |
def add_person_to_teams(person, team_names): |
|
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
81 |
"""Add `person` to the teams named in `team_names`.
|
82 |
||
83 |
`person` is provided as its own review, team membership status is always
|
|
84 |
`APPROVED`. This function will add users even to restricted teams.
|
|
85 |
||
86 |
A list of teams joined will be printed to stdout.
|
|
87 |
"""
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
88 |
person_set = getUtility(IPersonSet) |
6488.1.4
by Jonathan Lange
Slightly more error handling. |
89 |
teams_joined = [] |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
90 |
for team_name in team_names: |
91 |
team = person_set.getByName(team_name) |
|
6488.1.4
by Jonathan Lange
Slightly more error handling. |
92 |
if team is None: |
93 |
print "ERROR: %s not found." % (team_name,) |
|
94 |
continue
|
|
95 |
if not team.is_team: |
|
96 |
print "ERROR: %s is not a team." % (team_name,) |
|
97 |
continue
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
98 |
team.addMember( |
99 |
person, person, status=TeamMembershipStatus.APPROVED) |
|
6488.1.4
by Jonathan Lange
Slightly more error handling. |
100 |
teams_joined.append(team_name) |
101 |
print "teams: %s" % ' '.join(teams_joined) |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
102 |
|
103 |
||
104 |
def add_ssh_public_keys(person): |
|
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
105 |
"""Look for public keys and register them for `person`.
|
106 |
||
107 |
This function looks in ~/.ssh/id_rsa.pub and ~/.ssh/id_dsa.pub for SSH
|
|
108 |
public keys and registers them as SSH keys for `person`.
|
|
109 |
"""
|
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
110 |
ssh_dir = os.path.expanduser('~/.ssh') |
111 |
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 |
112 |
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. |
113 |
try: |
11332.1.1
by Steve Kowalik
Change how SSH keys are added in utilities/make-lp-user, no longer guess the |
114 |
public_key_file = open(filename, 'r') |
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
115 |
try: |
116 |
public_key = public_key_file.read() |
|
117 |
finally: |
|
118 |
public_key_file.close() |
|
119 |
except (OSError, IOError): |
|
120 |
continue
|
|
11332.1.1
by Steve Kowalik
Change how SSH keys are added in utilities/make-lp-user, no longer guess the |
121 |
key_set.new(person, public_key) |
122 |
print 'Registered SSH key: %s' % (filename,) |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
123 |
|
124 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
125 |
def parse_fingerprints(gpg_output): |
126 |
"""Find key fingerprints in "gpg --fingerprint <email>" output."""
|
|
127 |
line_prefix = re.compile('\s*Key fingerprint\s*=\s*') |
|
128 |
return [ |
|
129 |
''.join(re.sub(line_prefix, '', line).split()) |
|
130 |
for line in gpg_output.splitlines() |
|
131 |
if line_prefix.match(line) |
|
132 |
]
|
|
133 |
||
134 |
||
135 |
def run_native_gpg(arguments): |
|
136 |
"""Run GPG using the user's real keyring."""
|
|
137 |
# Need to override GNUPGHOME or we'll get a dummy GPG in a temp
|
|
138 |
# directory, which won't find any keys.
|
|
139 |
env = os.environ.copy() |
|
140 |
if 'GNUPGHOME' in env: |
|
141 |
del env['GNUPGHOME'] |
|
10427.4.8
by Jeroen Vermeulen
Beware of translated gpg, thanks adeuring for spotting that. |
142 |
|
143 |
# Prevent translated gpg output from messing up our parsing.
|
|
144 |
env['LC_ALL'] = 'C' |
|
145 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
146 |
command_line = ['gpg'] + arguments |
147 |
pipe = subprocess.Popen( |
|
148 |
command_line, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
149 |
stdout, stderr = pipe.communicate() |
|
150 |
if stderr != '': |
|
151 |
print stderr |
|
152 |
if pipe.returncode != 0: |
|
153 |
raise Exception('GPG error during "%s"' % ' '.join(command_line)) |
|
154 |
||
155 |
return stdout |
|
156 |
||
157 |
||
158 |
def add_gpg_key(person, fingerprint): |
|
159 |
"""Add the GPG key with the given fingerprint to `person`."""
|
|
160 |
run_native_gpg([ |
|
161 |
'--keyserver', 'keyserver.launchpad.dev', |
|
162 |
'--send-key', fingerprint |
|
163 |
])
|
|
164 |
||
165 |
gpghandler = getUtility(IGPGHandler) |
|
166 |
key = gpghandler.retrieveKey(fingerprint) |
|
167 |
||
168 |
gpgkeyset = getUtility(IGPGKeySet) |
|
169 |
if gpgkeyset.getByFingerprint(fingerprint) is not None: |
|
170 |
# We already have this key.
|
|
171 |
return
|
|
172 |
||
173 |
algorithm = GPGKeyAlgorithm.items[key.algorithm] |
|
174 |
can_encrypt = True |
|
175 |
lpkey = gpgkeyset.new( |
|
176 |
person.id, key.keyid, fingerprint, key.keysize, algorithm, |
|
177 |
active=True, can_encrypt=can_encrypt) |
|
178 |
Store.of(person).add(lpkey) |
|
179 |
||
180 |
||
181 |
def attach_gpg_keys(email, person): |
|
182 |
"""Attach the GPG key(s) for `email` to `person`."""
|
|
183 |
output = run_native_gpg(['--fingerprint', email]) |
|
184 |
||
185 |
fingerprints = parse_fingerprints(output) |
|
186 |
if len(fingerprints) == 0: |
|
187 |
print "No GPG key fingerprints found!" |
|
188 |
for fingerprint in fingerprints: |
|
189 |
add_gpg_key(person, fingerprint) |
|
190 |
||
191 |
||
192 |
def parse_args(arguments): |
|
193 |
"""Parse command-line arguments.
|
|
194 |
||
195 |
:return: options object. Among the options are username (a
|
|
196 |
string) and optionally teams (a list).
|
|
197 |
"""
|
|
198 |
parser = OptionParser(description="Create a local Launchpad user.") |
|
199 |
parser.add_option( |
|
200 |
'-e', '--email', action='store', dest='email', default=None, |
|
201 |
help="Email address; set to use real GPG key for this address.") |
|
10427.4.4
by Jeroen Vermeulen
Better options processing. |
202 |
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
203 |
options, args = parser.parse_args(arguments) |
204 |
if len(args) == 0: |
|
205 |
print __doc__ |
|
10427.4.4
by Jeroen Vermeulen
Better options processing. |
206 |
sys.exit(2) |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
207 |
|
208 |
options.username = args[0] |
|
209 |
options.teams = args[1:] |
|
210 |
||
211 |
return options |
|
212 |
||
213 |
||
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
214 |
def main(arguments): |
6488.1.3
by Jonathan Lange
Docstrings ahoy! |
215 |
"""Run the script."""
|
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
216 |
options = parse_args(arguments) |
217 |
if options.email is None: |
|
218 |
email = '%s@example.com' % options.username |
|
219 |
else: |
|
220 |
email = options.email |
|
221 |
||
10427.4.4
by Jeroen Vermeulen
Better options processing. |
222 |
execute_zcml_for_scripts() |
223 |
transaction.begin() |
|
224 |
||
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
225 |
person = make_person(options.username, email) |
226 |
add_person_to_teams(person, options.teams) |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
227 |
add_ssh_public_keys(person) |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
228 |
|
229 |
if options.email is not None: |
|
230 |
attach_gpg_keys(options.email, person) |
|
231 |
||
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
232 |
transaction.commit() |
10427.4.2
by Jeroen Vermeulen
Moved user/gpg creation into make-lp-user. |
233 |
|
6488.1.1
by Jonathan Lange
Initial commit of utility to make a user on development environment. |
234 |
return 0 |
235 |
||
236 |
||
237 |
if __name__ == '__main__': |
|
238 |
sys.exit(main(sys.argv[1:])) |