Merge lp:~mvo/aptdaemon/add-license-key-call-from-server into lp:aptdaemon
- add-license-key-call-from-server
- Merge into main
Proposed by
Michael Vogt
Status: | Merged |
---|---|
Merged at revision: | 703 |
Proposed branch: | lp:~mvo/aptdaemon/add-license-key-call-from-server |
Merge into: | lp:aptdaemon |
Diff against target: |
993 lines (+614/-113) 14 files modified
NEWS (+10/-0) aptdaemon/client.py (+27/-0) aptdaemon/core.py (+34/-2) aptdaemon/enums.py (+17/-0) aptdaemon/piston/scaclient.py (+55/-0) aptdaemon/worker.py (+114/-0) helper/ubuntu-license-key-helper (+68/-0) setup.py (+6/-2) tests/repo/Packages (+137/-96) tests/repo/Release (+4/-4) tests/repo/Release.gpg (+7/-7) tests/test_client.py (+40/-1) tests/test_helper.py (+60/-0) tests/test_worker.py (+35/-1) |
To merge this branch: | bzr merge lp:~mvo/aptdaemon/add-license-key-call-from-server |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Aptdaemon Developers | Pending | ||
Review via email: mp+81860@code.launchpad.net |
Commit message
Description of the change
This branch adds system wide license keys. The keys are obtained via a helper utility directly from the server.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NEWS' |
2 | --- NEWS 2011-10-08 16:23:14 +0000 |
3 | +++ NEWS 2011-11-10 14:28:46 +0000 |
4 | @@ -9,6 +9,7 @@ |
5 | - Freeze (copy) the dpkg status file during a dpkg call to allow |
6 | simulating other transactions with the frozen dpkg status |
7 | |
8 | + - Allow to install global license keys, see below |
9 | - Add compatibilty for py-gobject 3.0 to the client module by switching |
10 | to gobject from introspection repository |
11 | |
12 | @@ -30,6 +31,15 @@ |
13 | - aptdaemon.test.Chroot now has got new methods to handle faked cdrom |
14 | repositories: add_cdrom_repository(), mount_cdrom() and unmount_cdrom() |
15 | |
16 | + - org.debian.apt.transaction D-Bus interface: The Download and Space |
17 | + properties are now of type Int64 (signed 64-bit integer) |
18 | + |
19 | + - org.debian.apt D-Bus interface: Add new AddLicenseKey method which |
20 | + allows to place a license key file at the loaction specified in the |
21 | + record/control field LicenseKeyPath of the corresponding package. |
22 | + |
23 | + - aptdaemon.client: New AptClient.add_license_key method. |
24 | + |
25 | - org.debian.apt D-Bus interface: Add the RebootRequired property. Should |
26 | be quite self-explanatory |
27 | |
28 | |
29 | === modified file 'aptdaemon/client.py' |
30 | --- aptdaemon/client.py 2011-08-17 11:23:20 +0000 |
31 | +++ aptdaemon/client.py 2011-11-10 14:28:46 +0000 |
32 | @@ -1536,6 +1536,33 @@ |
33 | return self._run_transaction("Clean", [], wait, reply_handler, |
34 | error_handler) |
35 | |
36 | + @deferable |
37 | + @convert_dbus_exception |
38 | + def add_license_key(self, pkg_name, json_token, server_name, wait=False, |
39 | + reply_handler=None, error_handler=None): |
40 | + """Install a license key to use a piece of proprietary software. |
41 | + |
42 | + :param pkg_name: The package which requires the license |
43 | + :param json_token: The oauth token in json format |
44 | + :param server_name: The server name (ubuntu-procduction, ubuntu-staging) |
45 | + |
46 | + :param wait: if True run the transaction immediately and return its exit |
47 | + state instead of the transaction itself. |
48 | + :param reply_handler: Callback function. If specified in combination |
49 | + with error_handler the method will be called asynchrounsouly. |
50 | + :param error_handler: Errback function. In case of an error the given |
51 | + callback gets the corresponding exception instance. |
52 | + :param defer: Run the method asynchrounsly and return a defer.Deferred. |
53 | + This options is only available as an keyword. |
54 | + |
55 | + :raises: dbus.DBusException |
56 | + |
57 | + :returns: An AptTransaction instance. |
58 | + """ |
59 | + return self._run_transaction("AddLicenseKey", |
60 | + [pkg_name, json_token, server_name], |
61 | + wait, reply_handler, |
62 | + error_handler) |
63 | |
64 | def _run_transaction(self, method_name, args, wait, reply_handler, |
65 | error_handler): |
66 | |
67 | === modified file 'aptdaemon/core.py' |
68 | --- aptdaemon/core.py 2011-09-15 14:23:50 +0000 |
69 | +++ aptdaemon/core.py 2011-11-10 14:28:46 +0000 |
70 | @@ -296,7 +296,10 @@ |
71 | enums.ROLE_CLEAN: \ |
72 | policykit1.PK_ACTION_CLEAN, |
73 | enums.ROLE_ENABLE_DISTRO_COMP: \ |
74 | - policykit1.PK_ACTION_CHANGE_REPOSITORY} |
75 | + policykit1.PK_ACTION_CHANGE_REPOSITORY, |
76 | + enums.ROLE_ADD_LICENSE_KEY: \ |
77 | + policykit1.PK_ACTION_INSTALL_OR_REMOVE_PACKAGES, |
78 | + } |
79 | |
80 | WRITABLE_PROPERTIES = ("HttpProxy", "Terminal", "AllowUnauthenticated", |
81 | "DebconfSocket", "MetaData", "Locale", |
82 | @@ -875,7 +878,8 @@ |
83 | if self.role not in [enums.ROLE_ADD_REPOSITORY, |
84 | enums.ROLE_ADD_VENDOR_KEY_FROM_KEYSERVER, |
85 | enums.ROLE_UPDATE_CACHE, |
86 | - enums.ROLE_INSTALL_PACKAGES]: |
87 | + enums.ROLE_INSTALL_PACKAGES, |
88 | + enums.ROLE_ADD_LICENSE_KEY]: |
89 | return_value(False) |
90 | flags = policykit1.CHECK_AUTH_NONE |
91 | for action in [policykit1.PK_ACTION_INSTALL_PACKAGES_FROM_NEW_REPO, |
92 | @@ -1856,6 +1860,34 @@ |
93 | mainloop.quit() |
94 | log.debug("Exit") |
95 | |
96 | + # pylint: disable-msg=C0103,C0322 |
97 | + @dbus_deferred_method(APTDAEMON_DBUS_INTERFACE, |
98 | + in_signature="sss", out_signature="s", |
99 | + sender_keyword="sender") |
100 | + def AddLicenseKey(self, pkg_name, json_token, server_name, sender): |
101 | + """Install a license key to use a piece of proprietary software. |
102 | + |
103 | + Requires the ``org.debian.apt.install-or-remove-packages`` |
104 | + :ref:`PolicyKit privilege <policykit>`. |
105 | + |
106 | + :param pkg_name: The name of the package which requires the license |
107 | + :type pkg_name: s |
108 | + :param json_token: The oauth token to use with the server in json format |
109 | + :type pkg_name: s |
110 | + :param pkg_name: The name of the server to use |
111 | + (ubuntu-production, ubuntu-staging) |
112 | + :type pkg_name: s |
113 | + |
114 | + :returns: The D-Bus path of the new transaction object which |
115 | + performs this action. |
116 | + """ |
117 | + log.info("AddLicenseKey() was called") |
118 | + return self._create_trans(enums.ROLE_ADD_LICENSE_KEY, sender, |
119 | + kwargs={'pkg_name': pkg_name, |
120 | + 'json_token' : json_token, |
121 | + 'server_name' : server_name, |
122 | + }) |
123 | + |
124 | @inline_callbacks |
125 | def _set_property(self, iface, name, value, sender): |
126 | """Helper to set a property on the properties D-Bus interface.""" |
127 | |
128 | === modified file 'aptdaemon/enums.py' |
129 | --- aptdaemon/enums.py 2011-10-24 12:30:38 +0000 |
130 | +++ aptdaemon/enums.py 2011-11-10 14:28:46 +0000 |
131 | @@ -35,6 +35,9 @@ |
132 | "ERROR_PACKAGE_MANAGER_FAILED", "ERROR_CACHE_BROKEN", |
133 | "ERROR_PACKAGE_UNAUTHENTICATED", "ERROR_INCOMPLETE_INSTALL", |
134 | "ERROR_UNREADABLE_PACKAGE_FILE", "ERROR_INVALID_PACKAGE_FILE", |
135 | + "ERROR_LICENSE_KEY_PATH_INVALID", "ERROR_LICENSE_KEY_PATH_UNSECURE", |
136 | + "ERROR_LICENSE_KEY_ALREADY_EXISTS", "ERROR_LICENSE_KEY_INVALID", |
137 | + "ERROR_LICENSE_KEY_SERVER", |
138 | "ERROR_UNKNOWN", |
139 | "STATUS_SETTING_UP", "STATUS_WAITING", "STATUS_WAITING_MEDIUM", |
140 | "STATUS_WAITING_CONFIG_FILE_PROMPT", "STATUS_WAITING_LOCK", |
141 | @@ -48,6 +51,7 @@ |
142 | "ROLE_REMOVE_VENDOR_KEY", "ROLE_FIX_INCOMPLETE_INSTALL", |
143 | "ROLE_FIX_BROKEN_DEPENDS", "ROLE_ADD_REPOSITORY", |
144 | "ROLE_ENABLE_DISTRO_COMP", "ROLE_CLEAN", "ROLE_RECONFIGURE", |
145 | + "ROLE_ADD_LICENSE_KEY", |
146 | "DOWNLOAD_DONE", "DOWNLOAD_AUTH_ERROR", "DOWNLOAD_ERROR", |
147 | "DOWNLOAD_FETCHING", "DOWNLOAD_IDLE", "DOWNLOAD_NETWORK_ERROR", |
148 | "PKG_INSTALLING", "PKG_CONFIGURING", "PKG_REMOVING", |
149 | @@ -143,6 +147,16 @@ |
150 | ERROR_UNREADABLE_PACKAGE_FILE = "error-unreadable-package-file" |
151 | #: The package file violates the Debian/Ubuntu policy |
152 | ERROR_INVALID_PACKAGE_FILE = "error-invalid-package-file" |
153 | +#: The license key path is not provided from a trusted source |
154 | +ERROR_LICENSE_KEY_PATH_INVALID = "error-license-key-path-invalid" |
155 | +#: The license key path is not provided from a trusted source |
156 | +ERROR_LICENSE_KEY_PATH_UNSECURE = "error-license-key-path-unsecure" |
157 | +#: The license key can not be retrivied from the server |
158 | +ERROR_LICENSE_KEY_SERVER = "error-license-key-server" |
159 | +#: The license key is already installed |
160 | +ERROR_LICENSE_KEY_ALREADY_EXISTS = "error-license-key-already-exists" |
161 | +#: The license key is invalid |
162 | +ERROR_LICENSE_KEY_INVALID = "error-license-key-invalid" |
163 | #: An unknown error occured. In most cases these are programming ones. |
164 | ERROR_UNKNOWN = "error-unknown" |
165 | |
166 | @@ -253,6 +267,8 @@ |
167 | ROLE_RECONFIGURE = "role-reconfigure" |
168 | #: The transaction will remove all downloaded package files. |
169 | ROLE_CLEAN = "role-clean" |
170 | +#: The transaction will add a license key to the system |
171 | +ROLE_ADD_LICENSE_KEY = "role-add-license-key" |
172 | |
173 | # DOWNLOAD STATES |
174 | #: The download has been completed. |
175 | @@ -434,6 +450,7 @@ |
176 | ROLE_ENABLE_DISTRO_COMP: _("Enabling component of the distribution failed"), |
177 | ROLE_CLEAN: _("Removing downloaded package files failed"), |
178 | ROLE_RECONFIGURE: _("Removing downloaded package files failed"), |
179 | + ROLE_ADD_LICENSE_KEY: _("Adding license key"), |
180 | ROLE_UNSET: "" |
181 | } |
182 | |
183 | |
184 | === added directory 'aptdaemon/piston' |
185 | === added file 'aptdaemon/piston/__init__.py' |
186 | === added file 'aptdaemon/piston/scaclient.py' |
187 | --- aptdaemon/piston/scaclient.py 1970-01-01 00:00:00 +0000 |
188 | +++ aptdaemon/piston/scaclient.py 2011-11-10 14:28:46 +0000 |
189 | @@ -0,0 +1,55 @@ |
190 | +from piston_mini_client import (PistonAPI, PistonResponseObject, |
191 | + returns_list_of, returns_json) |
192 | +from piston_mini_client.validators import (validate_pattern, validate, |
193 | + oauth_protected) |
194 | + |
195 | +# These are factored out as constants for if you need to work against a |
196 | +# server that doesn't support both schemes (like http-only dev servers) |
197 | +PUBLIC_API_SCHEME = 'http' |
198 | +AUTHENTICATED_API_SCHEME = 'https' |
199 | + |
200 | +class SoftwareCenterAgentAPI(PistonAPI): |
201 | + default_service_root = 'http://localhost:8000/api/2.0' |
202 | + |
203 | + @validate_pattern('lang', r'[^/]{1,9}$') |
204 | + @validate_pattern('series', r'[^/]{1,20}$') |
205 | + @validate_pattern('arch', r'[^/]{1,10}$') |
206 | + @returns_list_of(PistonResponseObject) |
207 | + def available_apps(self, lang, series, arch): |
208 | + """Retrieve the list of currently available apps for purchase.""" |
209 | + return self._get( |
210 | + 'applications/%s/ubuntu/%s/%s/' % (lang, series, arch), |
211 | + scheme=PUBLIC_API_SCHEME) |
212 | + |
213 | + @validate_pattern('lang', r'[^/]{1,9}$') |
214 | + @validate_pattern('series', r'[^/]{1,20}$') |
215 | + @validate_pattern('arch', r'[^/]{1,10}$') |
216 | + @oauth_protected |
217 | + @returns_list_of(PistonResponseObject) |
218 | + def available_apps_qa(self, lang, series, arch): |
219 | + """Retrieve the list of currently available apps for purchase.""" |
220 | + return self._get( |
221 | + 'applications_qa/%s/ubuntu/%s/%s/' % (lang, series, arch), |
222 | + scheme=AUTHENTICATED_API_SCHEME) |
223 | + |
224 | + @oauth_protected |
225 | + @validate('complete_only', bool, required=False) |
226 | + @returns_list_of(PistonResponseObject) |
227 | + def subscriptions_for_me(self, complete_only=False): |
228 | + return self._get('subscriptions/', |
229 | + args={'complete_only': complete_only}, |
230 | + scheme=AUTHENTICATED_API_SCHEME) |
231 | + |
232 | + @oauth_protected |
233 | + @validate('id', int) |
234 | + @returns_json |
235 | + def subscription_by_id(self, id=None): |
236 | + return self._get('subscription/%d' % (id), |
237 | + scheme=AUTHENTICATED_API_SCHEME) |
238 | + |
239 | + @validate_pattern('lang', r'[^/]{1,9}$') |
240 | + @returns_list_of(PistonResponseObject) |
241 | + def exhibits(self, lang): |
242 | + """Retrieve the list of currently published exhibits.""" |
243 | + return self._get( |
244 | + 'exhibits/%s/' % (lang)) |
245 | |
246 | === modified file 'aptdaemon/worker.py' |
247 | --- aptdaemon/worker.py 2011-09-18 06:31:09 +0000 |
248 | +++ aptdaemon/worker.py 2011-11-10 14:28:46 +0000 |
249 | @@ -25,6 +25,7 @@ |
250 | import logging |
251 | import os |
252 | import re |
253 | +import json |
254 | import shutil |
255 | import sys |
256 | import tempfile |
257 | @@ -61,6 +62,7 @@ |
258 | # core.Transaction.gettext |
259 | _ = lambda s: s |
260 | |
261 | + |
262 | class AptWorker(gobject.GObject): |
263 | |
264 | """Worker which processes transactions from the queue.""" |
265 | @@ -69,6 +71,9 @@ |
266 | gobject.TYPE_NONE, |
267 | (gobject.TYPE_PYOBJECT,))} |
268 | |
269 | + # the basedir under which license keys can be stored |
270 | + LICENSE_KEY_ROOTDIR = "/opt/" |
271 | + |
272 | def __init__(self, chroot=None): |
273 | """Initialize a new AptWorker instance.""" |
274 | gobject.GObject.__init__(self) |
275 | @@ -204,6 +209,8 @@ |
276 | elif trans.role == ROLE_UPDATE_CACHE: |
277 | self.update_cache(trans, **trans.kwargs) |
278 | # Process the transactions which require a consistent cache |
279 | + elif trans.role == ROLE_ADD_LICENSE_KEY: |
280 | + self.add_license_key(trans, **trans.kwargs) |
281 | elif self._cache and self._cache.broken_count: |
282 | broken = [pkg.name for pkg in self._cache if pkg.is_now_broken] |
283 | raise TransactionFailed(ERROR_CACHE_BROKEN, |
284 | @@ -1168,6 +1175,113 @@ |
285 | log.debug("Removing file %s", path) |
286 | os.remove(path) |
287 | |
288 | + def add_license_key(self, trans, pkg_name, json_token, server_name): |
289 | + """Add a license key data to the given package. |
290 | + |
291 | + Keyword arguemnts: |
292 | + trans -- the coresponding transaction |
293 | + pkg_name -- the name of the corresponding package |
294 | + json_token -- the oauth token as json |
295 | + server_name -- the server to use (ubuntu-production, ubuntu-staging) |
296 | + """ |
297 | + # set transaction state to downloading |
298 | + trans.status = STATUS_DOWNLOADING |
299 | + rootdir = apt_pkg.config["Dir"] |
300 | + license_key_helper = os.path.join( |
301 | + rootdir, "usr/share/aptdaemon/helper/ubuntu-license-key-helper") |
302 | + cmd = [license_key_helper, |
303 | + "--server", server_name, |
304 | + "--pkgname", pkg_name, |
305 | + ] |
306 | + proc = subprocess.Popen(cmd, |
307 | + stdin=subprocess.PIPE, |
308 | + stderr=subprocess.PIPE, |
309 | + stdout=subprocess.PIPE, |
310 | + preexec_fn=lambda: os.setuid(trans.uid), |
311 | + close_fds=True) |
312 | + # send json token to the process |
313 | + proc.stdin.write(json_token + "\n") |
314 | + # wait until it finishes |
315 | + while proc.poll() is None: |
316 | + while gobject.main_context_default().pending(): |
317 | + gobject.main_context_default().iteration() |
318 | + time.sleep(0.05) |
319 | + |
320 | + if proc.returncode != 0: |
321 | + stderr = unicode(proc.stderr.read(), |
322 | + sys.stdin.encoding or "UTF-8", |
323 | + errors="replace") |
324 | + raise TransactionFailed(ERROR_LICENSE_KEY_SERVER, stderr) |
325 | + |
326 | + # get data from stdout |
327 | + license_key_path = proc.stdout.readline().strip() |
328 | + license_key = proc.stdout.read() |
329 | + |
330 | + # ensure stuff is good |
331 | + if not license_key_path or not license_key: |
332 | + raise TransactionFailed( |
333 | + ERROR_LICENSE_KEY_SERVER, |
334 | + _("Recived no license key data from the server.")) |
335 | + |
336 | + # add license key if we have one |
337 | + self._add_license_key_to_system(pkg_name, |
338 | + license_key, |
339 | + license_key_path) |
340 | + |
341 | + |
342 | + def _add_license_key_to_system(self, pkg_name, license_key, license_key_path): |
343 | + # fixup path |
344 | + license_key_path = os.path.join(apt_pkg.config.find_dir("Dir"), |
345 | + license_key_path.lstrip("/")) |
346 | + |
347 | + # Perform some very basic security checks |
348 | + |
349 | + # Check content of the key |
350 | + if (license_key.strip().startswith("#!") or |
351 | + license_key.startswith("\x7fELF")): |
352 | + raise TransactionFailed(ERROR_LICENSE_KEY_INVALID, |
353 | + _("The license key is not allowed to " |
354 | + "contain executable code.")) |
355 | + # Perform some very basic security checks |
356 | + license_key_path = os.path.normpath(license_key_path) |
357 | + license_key_path_rootdir = os.path.join(apt_pkg.config["Dir"], |
358 | + self.LICENSE_KEY_ROOTDIR.lstrip("/"), |
359 | + pkg_name) |
360 | + if not license_key_path.startswith(license_key_path_rootdir): |
361 | + raise TransactionFailed(ERROR_LICENSE_KEY_PATH_INVALID, |
362 | + _("The license key path %s is invalid"), |
363 | + license_key_path) |
364 | + if os.path.lexists(license_key_path): |
365 | + raise TransactionFaild(ERROR_LICENSE_KEY_ALREADY_INSTALLED, |
366 | + _("The license key already exists: %s"), |
367 | + license_key_path) |
368 | + # Symlink attacks! |
369 | + if os.path.realpath(license_key_path) != license_key_path: |
370 | + raise TransactionFailed(ERROR_LICENSE_KEY_PATH_INVALID, |
371 | + _("The location of the license key is " |
372 | + "unsecure since it contains symbolic " |
373 | + "links. The path %s maps to %s"), |
374 | + license_key_path, |
375 | + os.path.realpath(licese_key_path)) |
376 | + # Check if the directory already exists |
377 | + if not os.path.isdir(os.path.dirname(license_key_path)): |
378 | + raise TransactionFailed(ERROR_LICENSE_KEY_PATH_INVALID, |
379 | + _("The directory where to install the key " |
380 | + "to doesn't exist yet: %s"), |
381 | + license_key_path) |
382 | + # write it |
383 | + log.info("Writing license key to '%s'" % license_key_path) |
384 | + old_umask = os.umask(18) |
385 | + try: |
386 | + with open(license_key_path, "w") as license_file: |
387 | + license_file.write(license_key) |
388 | + except IOError: |
389 | + raise TransactionFailed(ERROR_LICENSE_KEY_PATH_INVALID, |
390 | + _("Failed to write key file to: %s"), |
391 | + license_key_path) |
392 | + finally: |
393 | + os.umask(old_umask) |
394 | + |
395 | def _get_broken_details(self, trans, now=True): |
396 | """Return a message which provides debugging information about |
397 | broken packages. |
398 | |
399 | === added directory 'helper' |
400 | === added file 'helper/ubuntu-license-key-helper' |
401 | --- helper/ubuntu-license-key-helper 1970-01-01 00:00:00 +0000 |
402 | +++ helper/ubuntu-license-key-helper 2011-11-10 14:28:46 +0000 |
403 | @@ -0,0 +1,68 @@ |
404 | +#!/usr/bin/python |
405 | + |
406 | +import json |
407 | +from optparse import OptionParser |
408 | +import sys |
409 | + |
410 | +from aptdaemon.piston.scaclient import SoftwareCenterAgentAPI |
411 | +import piston_mini_client.auth |
412 | + |
413 | +import gettext |
414 | +gettext.install("aptdaemon") |
415 | + |
416 | +if __name__ == "__main__": |
417 | + |
418 | + parser = OptionParser() |
419 | + parser.add_option("-s", "--server", default="ubuntu-production") |
420 | + parser.add_option("-p", "--pkgname") |
421 | + (options, args) = parser.parse_args() |
422 | + |
423 | + # server to use |
424 | + if options.server == "ubuntu-production": |
425 | + server = "http://software-center.ubuntu.com/api/2.0" |
426 | + elif options.server == "ubuntu-staging": |
427 | + server = "https://sc.staging.ubuntu.com/api/2.0" |
428 | + else: |
429 | + raise Exception("Unknown license key server") |
430 | + SoftwareCenterAgentAPI.default_service_root = server |
431 | + |
432 | + # pkgname |
433 | + pkgname = options.pkgname |
434 | + |
435 | + # wait for oauth token on stdin |
436 | + json_token = sys.stdin.readline() |
437 | + token = json.loads(json_token) |
438 | + |
439 | + # get the data |
440 | + auth = piston_mini_client.auth.OAuthAuthorizer(token["token_key"], |
441 | + token["token_secret"], |
442 | + token["consumer_key"], |
443 | + token["consumer_secret"]) |
444 | + |
445 | + api = SoftwareCenterAgentAPI(auth=auth) |
446 | + |
447 | + |
448 | + try: |
449 | + subscriptions = api.subscriptions_for_me(complete_only=True) |
450 | + except piston_mini_client.APIError as e: |
451 | + sys.stderr.write(_("Failed to get the license key from " |
452 | + "the server.")) |
453 | + sys.exit(1) |
454 | + |
455 | + license_key = None |
456 | + license_key_path = None |
457 | + for subscription in subscriptions: |
458 | + if subscription.application["package_name"] == pkg_name: |
459 | + license_key = subscription.license_key |
460 | + license_key_path = subscription.license_key_path |
461 | + |
462 | + if license_key and license_key_path: |
463 | + sys.stdout.write(license_key_path) |
464 | + sys.stdout.write(license_key) |
465 | + sys.exit(0) |
466 | + |
467 | + # generic error |
468 | + sys.stderr.write(_("Failed to get the license key from " |
469 | + "the server.")) |
470 | + sys.exit(1) |
471 | + |
472 | |
473 | === modified file 'setup.py' |
474 | --- setup.py 2011-08-26 06:37:34 +0000 |
475 | +++ setup.py 2011-11-10 14:28:46 +0000 |
476 | @@ -20,7 +20,8 @@ |
477 | long_description=readme, |
478 | author="Sebastian Heinlein", |
479 | author_email="devel@glatzor.de", |
480 | - packages=["aptdaemon"], |
481 | + packages=["aptdaemon", |
482 | + "aptdaemon.piston"], |
483 | scripts=["aptd", "aptdcon"], |
484 | test_suite="unittest2.collector", |
485 | license="GNU LGPL", |
486 | @@ -47,7 +48,10 @@ |
487 | ["doc/aptd.1", "doc/aptdcon.1"]), |
488 | ("share/man/man7", |
489 | ["doc/org.debian.apt.7", |
490 | - "doc/org.debian.apt.transaction.7"])], |
491 | + "doc/org.debian.apt.transaction.7"]), |
492 | + ("share/aptdaemon/helper", |
493 | + glob.glob("helper/*")), |
494 | + ], |
495 | platforms="posix", |
496 | use_2to3=sys.version_info[0] >= 3, |
497 | ) |
498 | |
499 | === modified file 'tests/repo/Packages' |
500 | --- tests/repo/Packages 2011-01-10 07:37:44 +0000 |
501 | +++ tests/repo/Packages 2011-11-10 14:28:46 +0000 |
502 | @@ -1,61 +1,3 @@ |
503 | -Package: silly-fail |
504 | -Priority: extra |
505 | -Section: admin |
506 | -Installed-Size: 36 |
507 | -Maintainer: Sebastian Heinlein <devel@glatzor.de> |
508 | -Architecture: all |
509 | -Source: silly-packages |
510 | -Version: 0.1-0 |
511 | -Filename: ./silly-fail_0.1-0_all.deb |
512 | -Size: 1874 |
513 | -MD5sum: 623a67e49bb7a1351a9bf1ae72fc6cfb |
514 | -SHA1: 76417770f2b788b680ef18be66b5a6c4ec51bc62 |
515 | -SHA256: 45fea3eb64a427a288a90b12f42cc3a6abea8e8387efd4879b319db736890ebd |
516 | -Description: installation fails |
517 | - Silly packages is a set of packages which will break your package |
518 | - management tool. They are created only for debugging purposes. |
519 | - . |
520 | - This installation of this package will always fail. |
521 | - |
522 | -Package: silly-depend-base |
523 | -Priority: extra |
524 | -Section: admin |
525 | -Installed-Size: 32 |
526 | -Maintainer: Sebastian Heinlein <devel@glatzor.de> |
527 | -Architecture: all |
528 | -Source: silly-packages |
529 | -Version: 0.1-0 |
530 | -Depends: silly-base |
531 | -Filename: ./silly-depend-base_0.1-0_all.deb |
532 | -Size: 1812 |
533 | -MD5sum: 3ee7181283e4926558d2afdf7b2657f1 |
534 | -SHA1: 8294794b1727e22b123866f9124431a2c7b79380 |
535 | -SHA256: 5fa74f7bdc0d207188790419130330becb0cf7484a972762ed512090885016f9 |
536 | -Description: package depending on silly-base |
537 | - Silly packages is a set of packages which will break your package |
538 | - management tool. They are created only for debugging purposes. |
539 | - . |
540 | - This package depends on silly-base. |
541 | - |
542 | -Package: silly-config |
543 | -Priority: extra |
544 | -Section: admin |
545 | -Installed-Size: 44 |
546 | -Maintainer: Sebastian Heinlein <devel@glatzor.de> |
547 | -Architecture: all |
548 | -Source: silly-packages |
549 | -Version: 0.1-0 |
550 | -Filename: ./silly-config_0.1-0_all.deb |
551 | -Size: 1928 |
552 | -MD5sum: 565698b052640ed3d514f6b38ad457c7 |
553 | -SHA1: e7169cc58f10e8ff9481cf31b2ffb947bc99f617 |
554 | -SHA256: 255f025bae5b24a91158e7daa986f9bf59146ab1895f39452104eb97c412d190 |
555 | -Description: wants to update a locally changed config file |
556 | - Silly packages is a set of packages which will break your package |
557 | - management tool. They are created only for debugging purposes. |
558 | - . |
559 | - This package will install a configuration file. |
560 | - |
561 | Package: silly-postinst-input |
562 | Priority: extra |
563 | Section: admin |
564 | @@ -75,44 +17,6 @@ |
565 | . |
566 | This package will wait for user input in the postinst script. |
567 | |
568 | -Package: silly-base |
569 | -Priority: extra |
570 | -Section: admin |
571 | -Installed-Size: 44 |
572 | -Maintainer: Sebastian Heinlein <devel@glatzor.de> |
573 | -Architecture: all |
574 | -Source: silly-packages (0.1-0) |
575 | -Version: 0.1-0update1 |
576 | -Filename: ./silly-base_0.1-0update1_all.deb |
577 | -Size: 1934 |
578 | -MD5sum: 8e20af56a63a1e0cf40db3b0d07e7989 |
579 | -SHA1: 7ce87423d9c7a734478c464021994944d07fbf1b |
580 | -SHA256: d3693c0e3e7a9519b2833fdf1301c7e03e0620edf15b95b4c7329d9eb0bee553 |
581 | -Description: working package |
582 | - Silly packages is a set of packages which will break your package |
583 | - management tool. They are created only for debugging purposes. |
584 | - . |
585 | - This package doesn't contain any files and should always be installable. |
586 | - |
587 | -Package: silly-base |
588 | -Priority: extra |
589 | -Section: admin |
590 | -Installed-Size: 32 |
591 | -Maintainer: Sebastian Heinlein <devel@glatzor.de> |
592 | -Architecture: all |
593 | -Source: silly-packages |
594 | -Version: 0.1-0 |
595 | -Filename: ./silly-base_0.1-0_all.deb |
596 | -Size: 1824 |
597 | -MD5sum: 81ba1cf86142c466f35a36a11b5b7b52 |
598 | -SHA1: f949c8e5962a43fbcd4f7d67df0ebe741052c497 |
599 | -SHA256: a7c2a30abdb6488d5c3d2894db398f5dfafbc6be098da1135822be4e3ac94b32 |
600 | -Description: working package |
601 | - Silly packages is a set of packages which will break your package |
602 | - management tool. They are created only for debugging purposes. |
603 | - . |
604 | - This package doesn't contain any files and should always be installable. |
605 | - |
606 | Package: gstreamer0.10-silly |
607 | Priority: extra |
608 | Section: admin |
609 | @@ -133,6 +37,25 @@ |
610 | . |
611 | This package is a GStreamer test plugin package. |
612 | |
613 | +Package: silly-base |
614 | +Priority: extra |
615 | +Section: admin |
616 | +Installed-Size: 44 |
617 | +Maintainer: Sebastian Heinlein <devel@glatzor.de> |
618 | +Architecture: all |
619 | +Source: silly-packages (0.1-0) |
620 | +Version: 0.1-0update1 |
621 | +Filename: ./silly-base_0.1-0update1_all.deb |
622 | +Size: 1934 |
623 | +MD5sum: 8e20af56a63a1e0cf40db3b0d07e7989 |
624 | +SHA1: 7ce87423d9c7a734478c464021994944d07fbf1b |
625 | +SHA256: d3693c0e3e7a9519b2833fdf1301c7e03e0620edf15b95b4c7329d9eb0bee553 |
626 | +Description: working package |
627 | + Silly packages is a set of packages which will break your package |
628 | + management tool. They are created only for debugging purposes. |
629 | + . |
630 | + This package doesn't contain any files and should always be installable. |
631 | + |
632 | Package: silly-essential |
633 | Essential: yes |
634 | Priority: extra |
635 | @@ -153,6 +76,25 @@ |
636 | . |
637 | This package is an essential one. |
638 | |
639 | +Package: silly-base |
640 | +Priority: extra |
641 | +Section: admin |
642 | +Installed-Size: 32 |
643 | +Maintainer: Sebastian Heinlein <devel@glatzor.de> |
644 | +Architecture: all |
645 | +Source: silly-packages |
646 | +Version: 0.1-0 |
647 | +Filename: ./silly-base_0.1-0_all.deb |
648 | +Size: 1824 |
649 | +MD5sum: 81ba1cf86142c466f35a36a11b5b7b52 |
650 | +SHA1: f949c8e5962a43fbcd4f7d67df0ebe741052c497 |
651 | +SHA256: a7c2a30abdb6488d5c3d2894db398f5dfafbc6be098da1135822be4e3ac94b32 |
652 | +Description: working package |
653 | + Silly packages is a set of packages which will break your package |
654 | + management tool. They are created only for debugging purposes. |
655 | + . |
656 | + This package doesn't contain any files and should always be installable. |
657 | + |
658 | Package: silly-important |
659 | Priority: important |
660 | Section: admin |
661 | @@ -172,6 +114,27 @@ |
662 | . |
663 | This package is an essential one. |
664 | |
665 | +Package: silly-license |
666 | +Essential: yes |
667 | +Priority: extra |
668 | +Section: admin |
669 | +Installed-Size: 44 |
670 | +Maintainer: Sebastian Heinlein <devel@glatzor.de> |
671 | +Architecture: all |
672 | +Source: silly-packages |
673 | +Version: 0.1-0 |
674 | +Filename: ./silly-license_0.1-0_all.deb |
675 | +Size: 3884 |
676 | +MD5sum: 8498a97dd25e37760f26e215dc16668e |
677 | +SHA1: b42846a26132fc771ec2bd8e7eb07e17041c501b |
678 | +SHA256: 1eed24cbaa3e5dd54a7e5302b98ab8b1e97c1433f6e9bb1e14f641994249a323 |
679 | +Description: package with optional license key |
680 | + Silly packages is a set of packages which will break your package |
681 | + management tool. They are created only for debugging purposes. |
682 | + . |
683 | + This package provides allows to install an optional license key file. |
684 | +Licensekeypath: /opt/silly-license/NASTY.KEY |
685 | + |
686 | Package: silly-broken |
687 | Priority: extra |
688 | Section: admin |
689 | @@ -192,3 +155,81 @@ |
690 | . |
691 | This package cannot be installed because of a missing dependency. |
692 | |
693 | +Package: silly-config |
694 | +Priority: extra |
695 | +Section: admin |
696 | +Installed-Size: 44 |
697 | +Maintainer: Sebastian Heinlein <devel@glatzor.de> |
698 | +Architecture: all |
699 | +Source: silly-packages |
700 | +Version: 0.1-0 |
701 | +Filename: ./silly-config_0.1-0_all.deb |
702 | +Size: 1928 |
703 | +MD5sum: 565698b052640ed3d514f6b38ad457c7 |
704 | +SHA1: e7169cc58f10e8ff9481cf31b2ffb947bc99f617 |
705 | +SHA256: 255f025bae5b24a91158e7daa986f9bf59146ab1895f39452104eb97c412d190 |
706 | +Description: wants to update a locally changed config file |
707 | + Silly packages is a set of packages which will break your package |
708 | + management tool. They are created only for debugging purposes. |
709 | + . |
710 | + This package will install a configuration file. |
711 | + |
712 | +Package: silly-depend-base-lintian-broken |
713 | +Priority: extra |
714 | +Section: admin |
715 | +Installed-Size: 32 |
716 | +Architecture: all |
717 | +Source: silly-packages |
718 | +Version: 0.1-0 |
719 | +Depends: silly-base |
720 | +Filename: ./silly-depend-base-lintian-broken_0.1-0_all.deb |
721 | +Size: 1758 |
722 | +MD5sum: ba9e0b746b08fae8f8a8fbb4cf9ba41e |
723 | +SHA1: 8bcaf6034b09383e461f0e366762e6b6683e69e2 |
724 | +SHA256: ff1302170d232c21ab66f332e38c51b2af9b6d06d8f377ae5944465be9467c22 |
725 | +Description: package depending on silly-base (but lintian broken) |
726 | + Silly packages is a set of packages which will break your package |
727 | + management tool. They are created only for debugging purposes. |
728 | + . |
729 | + This package depends on silly-base and has no "Maintainer" set |
730 | + and the file owner is totally wrong so lintian complains about it. |
731 | + |
732 | +Package: silly-fail |
733 | +Priority: extra |
734 | +Section: admin |
735 | +Installed-Size: 36 |
736 | +Maintainer: Sebastian Heinlein <devel@glatzor.de> |
737 | +Architecture: all |
738 | +Source: silly-packages |
739 | +Version: 0.1-0 |
740 | +Filename: ./silly-fail_0.1-0_all.deb |
741 | +Size: 1874 |
742 | +MD5sum: 623a67e49bb7a1351a9bf1ae72fc6cfb |
743 | +SHA1: 76417770f2b788b680ef18be66b5a6c4ec51bc62 |
744 | +SHA256: 45fea3eb64a427a288a90b12f42cc3a6abea8e8387efd4879b319db736890ebd |
745 | +Description: installation fails |
746 | + Silly packages is a set of packages which will break your package |
747 | + management tool. They are created only for debugging purposes. |
748 | + . |
749 | + This installation of this package will always fail. |
750 | + |
751 | +Package: silly-depend-base |
752 | +Priority: extra |
753 | +Section: admin |
754 | +Installed-Size: 32 |
755 | +Maintainer: Sebastian Heinlein <devel@glatzor.de> |
756 | +Architecture: all |
757 | +Source: silly-packages |
758 | +Version: 0.1-0 |
759 | +Depends: silly-base |
760 | +Filename: ./silly-depend-base_0.1-0_all.deb |
761 | +Size: 1812 |
762 | +MD5sum: 3ee7181283e4926558d2afdf7b2657f1 |
763 | +SHA1: 8294794b1727e22b123866f9124431a2c7b79380 |
764 | +SHA256: 5fa74f7bdc0d207188790419130330becb0cf7484a972762ed512090885016f9 |
765 | +Description: package depending on silly-base |
766 | + Silly packages is a set of packages which will break your package |
767 | + management tool. They are created only for debugging purposes. |
768 | + . |
769 | + This package depends on silly-base. |
770 | + |
771 | |
772 | === modified file 'tests/repo/Release' |
773 | --- tests/repo/Release 2011-01-10 07:37:44 +0000 |
774 | +++ tests/repo/Release 2011-11-10 14:28:46 +0000 |
775 | @@ -1,10 +1,10 @@ |
776 | -Date: Mo, 10 Jan 2011 07:25:04 UTC |
777 | +Date: Di, 23 Aug 2011 11:53:15 UTC |
778 | MD5Sum: |
779 | - 76890eae32625a32d270e667eadf7672 6466 Packages |
780 | + a4c8c6d48d8429c070d8b2a19c900428 7902 Packages |
781 | d41d8cd98f00b204e9800998ecf8427e 0 Release |
782 | SHA1: |
783 | - ad2d57d7fb357429bdf72bd84a30a0ecaf427ccf 6466 Packages |
784 | + 5a3ddd070333e9954d92c20397883a5e58ca86e0 7902 Packages |
785 | da39a3ee5e6b4b0d3255bfef95601890afd80709 0 Release |
786 | SHA256: |
787 | - 0a755d4bc1cf098032ba2b74764fcf8f5c22d0c0e5944a0d63032db55af036fa 6466 Packages |
788 | + b7d04a99c3907fa1b0521f2130935fc48597d56739134d2e5453635bf530c015 7902 Packages |
789 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 Release |
790 | |
791 | === modified file 'tests/repo/Release.gpg' |
792 | --- tests/repo/Release.gpg 2011-01-10 07:37:44 +0000 |
793 | +++ tests/repo/Release.gpg 2011-11-10 14:28:46 +0000 |
794 | @@ -1,11 +1,11 @@ |
795 | -----BEGIN PGP SIGNATURE----- |
796 | Version: GnuPG v1.4.10 (GNU/Linux) |
797 | |
798 | -iQEcBAABCAAGBQJNKrRcAAoJEGg8U8fPmC0Y0bgIAMJUX9WLV2KMJFtIts+6mI+J |
799 | -stbq5GviUNPMVlp1eoVY4aGG+DHx0xtMBfxiBbW6QBrreAttrxXujwe1Jn85qcbn |
800 | -Gzz6rSvK999KZN/XjZskKa01hcpA2qYuRLn0buJ2BWno9jBmaZqxbL7aKargh9LJ |
801 | -dVDk+/Bw4inTN7I7iboQDGiUTGH88IB4kCO1Xu8hKExicoKvfSu6JtIaTCKhqbpm |
802 | -F0PLq/tXwSaBAeHzHqvKXDi5YOFVmeePv6ACUq/MEi3wnvRt+LRIyaZW+TBIc3zW |
803 | -yqyeQjTZ2DM9JoE+8F9e4M93KI+t1jwkcM2fWYmpar3ThoLLjdm+KpO5xTVtkvw= |
804 | -=6oo7 |
805 | +iQEcBAABCAAGBQJOU5UdAAoJEGg8U8fPmC0Y8b0IAJJx/g2AXbf743kynB8hM87B |
806 | +OzBEdOol3ekdCnryiwxCRiUS1eNCHl2WUMD2wbC7aTU34fmJk7cjAoCiBIEImJXS |
807 | +EFN56YM4nhHoC1dUvOsaNHTMzkHpAuYO1Fjy0WiBELqgk4g/+ADZWiJa8zyFghpi |
808 | +g48GFMLHBpfNL53MJFwBLjORCBNtrZLhUi0oXkzyRM81gi6k6ds09pyyUiJwdAI8 |
809 | +ovSPbFHzqSiuefRtxpQk9cyvuaUD40XLAwHBIW2mLOvXsYocRwhR7XCA2d9rJuvO |
810 | +EXxb2ALypcwHDZEh2FtNZwbqK+7BNf4RPIAVFjzp7ORB3BLEqyDiQdmUKlEqqZ8= |
811 | +=mZj1 |
812 | -----END PGP SIGNATURE----- |
813 | |
814 | === added file 'tests/repo/silly-license_0.1-0_all.deb' |
815 | Binary files tests/repo/silly-license_0.1-0_all.deb 1970-01-01 00:00:00 +0000 and tests/repo/silly-license_0.1-0_all.deb 2011-11-10 14:28:46 +0000 differ |
816 | === modified file 'tests/test_client.py' |
817 | --- tests/test_client.py 2011-09-15 14:23:50 +0000 |
818 | +++ tests/test_client.py 2011-11-10 14:28:46 +0000 |
819 | @@ -6,8 +6,10 @@ |
820 | import time |
821 | import unittest2 |
822 | |
823 | +import dbus |
824 | import defer |
825 | -import dbus |
826 | +import os |
827 | +import json |
828 | |
829 | import aptdaemon.client |
830 | import aptdaemon.loop |
831 | @@ -77,6 +79,43 @@ |
832 | exit = f(*args, wait=True) |
833 | self.assertEqual(exit, aptdaemon.enums.EXIT_SUCCESS) |
834 | |
835 | + def test_add_license_key(self): |
836 | + os.makedirs(os.path.join(self.chroot.path, "opt/silly-pkg")) |
837 | + helper_dir = os.path.join(self.chroot.path, "usr/share/aptdaemon/helper/") |
838 | + os.makedirs(helper_dir) |
839 | + # data |
840 | + license_key = "Bli bla blub. I am a BLOB" |
841 | + license_key_path = "/opt/silly-pkg/NASTY.KEY" |
842 | + # write out mock helper |
843 | + helper = os.path.join(helper_dir, "ubuntu-license-key-helper") |
844 | + f=open(helper, "w") |
845 | + f.write("""#!/bin/sh |
846 | +echo "%s" |
847 | +echo -n "%s" |
848 | +""" % (license_key_path, license_key)) |
849 | + f.close() |
850 | + os.chmod(helper, 0755) |
851 | + # run test |
852 | + chroot_license_key_path = os.path.join( |
853 | + self.chroot.path, license_key_path[1:]) |
854 | + client = aptdaemon.client.AptClient(self.bus) |
855 | + json_token = json.dumps({'token_key' : 'key', |
856 | + 'token_secret' : 'token_secret', |
857 | + 'consumer_key' : 'consumer_key', |
858 | + 'consumer_secret' : 'consumer_secret', |
859 | + 'subscription_id' : '99', |
860 | + 'api_version' : '2.0', |
861 | + }) |
862 | + trans = client.add_license_key( |
863 | + "silly-pkg", json_token, "mock") |
864 | + trans.connect("finished", self._on_finished) |
865 | + trans.run() |
866 | + aptdaemon.loop.mainloop.run() |
867 | + self.assertEqual(trans.exit, aptdaemon.enums.EXIT_SUCCESS, |
868 | + trans.error) |
869 | + self.assertEqual(license_key, open(chroot_license_key_path, "r").read(), |
870 | + "Specified and stored license key don't match") |
871 | + |
872 | |
873 | if __name__ == "__main__": |
874 | if DEBUG: |
875 | |
876 | === added file 'tests/test_helper.py' |
877 | --- tests/test_helper.py 1970-01-01 00:00:00 +0000 |
878 | +++ tests/test_helper.py 2011-11-10 14:28:46 +0000 |
879 | @@ -0,0 +1,60 @@ |
880 | +#!/usr/bin/env python |
881 | +# -*- coding: utf-8 -*- |
882 | +"""Tests the helper scripts.""" |
883 | + |
884 | +import logging |
885 | +import time |
886 | +import unittest2 |
887 | + |
888 | +import dbus |
889 | +import defer |
890 | +import os |
891 | +import json |
892 | +import subprocess |
893 | + |
894 | +import aptdaemon.client |
895 | +import aptdaemon.loop |
896 | +import aptdaemon.enums |
897 | + |
898 | +import aptdaemon.test |
899 | + |
900 | +class HelperTest(aptdaemon.test.AptDaemonTestCase): |
901 | + |
902 | + def setUp(self): |
903 | + basedir = os.path.dirname(__file__) |
904 | + self.basedir = os.path.abspath(os.path.join(basedir, "..")) |
905 | + self.helperdir = os.path.join(self.basedir, "helper") |
906 | + |
907 | + def test_ubuntu_license_key_helper(self): |
908 | + license_key_helper = os.path.join( |
909 | + self.helperdir, "ubuntu-license-key-helper") |
910 | + |
911 | + os.environ["PYTHONPATH"] = self.basedir |
912 | + |
913 | + p = subprocess.Popen([license_key_helper, |
914 | + "--pkgname", "2vcard", |
915 | + "--server", "ubuntu-production"], |
916 | + stdin=subprocess.PIPE, |
917 | + stdout=subprocess.PIPE, |
918 | + stderr=subprocess.PIPE) |
919 | + token = {} |
920 | + token["token_key"] = "foo" |
921 | + token["token_secret"] = "bar" |
922 | + token["consumer_key"] = "baz" |
923 | + token["consumer_secret"] = "foobar" |
924 | + #print json.dumps(token) |
925 | + p.stdin.write(json.dumps(token) + "\n") |
926 | + p.wait() |
927 | + # it fails, that is expected |
928 | + self.assertEqual(p.returncode, 1) |
929 | + stderr = p.stderr.read() |
930 | + stdout = p.stdout.read() |
931 | + self.assertEqual(stdout, "") |
932 | + self.assertEqual( |
933 | + stderr, "Failed to get the license key from the server.") |
934 | + |
935 | + |
936 | +if __name__ == "__main__": |
937 | + unittest2.main() |
938 | + |
939 | +# vim: ts=4 et sts=4 |
940 | |
941 | === modified file 'tests/test_worker.py' |
942 | --- tests/test_worker.py 2011-09-18 06:29:49 +0000 |
943 | +++ tests/test_worker.py 2011-11-10 14:28:46 +0000 |
944 | @@ -30,7 +30,6 @@ |
945 | import dbus |
946 | import gobject |
947 | |
948 | - |
949 | import aptdaemon.test |
950 | from aptdaemon.worker import AptWorker |
951 | from aptdaemon.core import Transaction |
952 | @@ -312,6 +311,41 @@ |
953 | self.worker._cache.open() |
954 | self.assertEqual(self.worker._cache.broken_count, 0) |
955 | |
956 | + def test_add_license_key_unsecure(self): |
957 | + """Test if we refuse to install license key files to an unsecure |
958 | + location.""" |
959 | + self.chroot.add_test_repository(copy_sig=False) |
960 | + # Should fail because of an untrusted source |
961 | + license_key = "NASTY_BLOB" |
962 | + license_key_path = "/opt/silly-license/NASTY.KEY" |
963 | + pkg_name = "silly-license" |
964 | + self.assertRaises(errors.TransactionFailed, |
965 | + self.worker._add_license_key_to_system, |
966 | + pkg_name, license_key, license_key_path) |
967 | + |
968 | + def test_add_license_key(self): |
969 | + """Test the installation of license key files.""" |
970 | + self.chroot.add_test_repository() |
971 | + # Check if we don't allow to install executables |
972 | + with open("/bin/ls", "r") as sample_exec: |
973 | + license_key = sample_exec.read() |
974 | + license_key_path = "/opt/silly-license/NASTY.KEY" |
975 | + pkg_name = "silly-license" |
976 | + self.assertRaises(errors.TransactionFailed, |
977 | + self.worker._add_license_key_to_system, |
978 | + pkg_name, license_key, license_key_path) |
979 | + # Should finally work |
980 | + os.makedirs(os.path.join( |
981 | + aptdaemon.worker.apt_pkg.config["Dir"], "opt/silly-license/")) |
982 | + license_key = "some key" |
983 | + license_key_path = "/opt/silly-license/NASTY.KEY" |
984 | + self.worker._add_license_key_to_system(pkg_name, license_key, license_key_path) |
985 | + # Check the content of the installed key |
986 | + license_key_path = os.path.join(aptdaemon.worker.apt_pkg.config["Dir"], |
987 | + "opt/silly-license/NASTY.KEY") |
988 | + self.assertEqual(license_key, open(license_key_path).read(), |
989 | + "Content of license key doesn't match") |
990 | + |
991 | |
992 | if __name__ == "__main__": |
993 | unittest2.main() |