Merge lp:~jason-hobbs/maas/use-key-text into lp:~maas-committers/maas/trunk

Proposed by Jason Hobbs
Status: Merged
Approved by: Jason Hobbs
Approved revision: no longer in the source branch.
Merged at revision: 2262
Proposed branch: lp:~jason-hobbs/maas/use-key-text
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 202 lines (+98/-37)
4 files modified
contrib/preseeds_v2/generic (+58/-6)
etc/maas/drivers.yaml (+8/-1)
src/maasserver/tests/test_third_party_drivers.py (+5/-26)
src/maasserver/third_party_drivers.py (+27/-4)
To merge this branch: bzr merge lp:~jason-hobbs/maas/use-key-text
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+215517@code.launchpad.net

Commit message

Insert the repository key directly into the yaml and preseed rather than retrieving it insecurely over http. This prevents MITM attacks when adding packages from the repository.

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

 * hard coded 'trusty' seems wrong in multiple places
 * you replaced what *was* a public key in
   apt-setup/local0/key
   with a keyring. Does something under the covers just handle either?

   Will updates to that repo work ? ie, will the key be installed
   into the target system properly?

 * test "$expected_sha256" = "$actual_sha256"
   no one is going to be able to look at a log and see what went wrong here
   this is repeated line again with the udeb.

 * it'd be nice to have some doc on how you make a keyring from a key
   to reduce the unfriendly binary content in the drivers.yaml file.

   Also, info on how to list what key is in that keyring.

 * i wonder if upgrades work (replacement of 'key' and 'key_binary' in third_party_drivers.py)

 * modprobe <driver>
   what if the driver is already loaded ? (which is likely if the booted kernel
   contains this driver).

Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

Scott,

Thanks for the review; responses below.

On 04/14/2014 03:37 PM, Scott Moser wrote:
> * hard coded 'trusty' seems wrong in multiple places

Yes, although it isn't new in this patch.

> * you replaced what *was* a public key in
> apt-setup/local0/key
> with a keyring. Does something under the covers just handle either?

Although it's called a keyring, it's just a key. It's the same as if you
exported a single key from gpg. I can rename it to pubkey.gpg to make
it clearer that it's just a single key.

> Will updates to that repo work ? ie, will the key be installed
> into the target system properly?

Yes, this has been tested.

> * test "$expected_sha256" = "$actual_sha256"
> no one is going to be able to look at a log and see what went wrong here
> this is repeated line again with the udeb.

Ok, good point, I will make it output some error message.

> * it'd be nice to have some doc on how you make a keyring from a key
> to reduce the unfriendly binary content in the drivers.yaml file.
>
> Also, info on how to list what key is in that keyring.

Ok, will do.

> * i wonder if upgrades work (replacement of 'key' and 'key_binary' in third_party_drivers.py)

This has never been released so it doesn't matter, but aren't unmodified
conf files replaced on upgrade?

> * modprobe <driver>
> what if the driver is already loaded ? (which is likely if the booted kernel
> contains this driver).

modprobe returns 0 if the driver is already loaded.

Thanks,
Jason

Revision history for this message
Andres Rodriguez (andreserl) wrote :

Thr trusty bits shiould be changed to {{node.release}} IIRC

Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

I'm not overly inclined to deal with the trusty hardcoded issue in this branch since it didn't originate in this branch and isn't needed to accomplish this branch's goal. If it needs to be addressed soon, I have a cleanup branch going it can go into.

Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

Scott - I think all the points you brought up should be addressed now.

Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

> Scott - I think all the points you brought up should be addressed now.

With the exception of the trusty hardcoded thing!

Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm now! hardcoding of trusty fix is coming in a different branch.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'contrib/preseeds_v2/generic'
2--- contrib/preseeds_v2/generic 2014-04-10 16:41:55 +0000
3+++ contrib/preseeds_v2/generic 2014-04-14 21:33:28 +0000
4@@ -27,15 +27,14 @@
5 {{def driver_preseed_data}}
6 {{if third_party_drivers and driver}}
7 # Third party driver support.
8-d-i preseed/early_command \
9- string wget -O - {{driver['repository']}}/dists/trusty/main/debian-installer/binary-amd64/Packages \
10- | wget -O /tmp/driver.udeb {{driver['repository']}}/$(grep ^Filename.*$(uname -r) \
11- | cut -f 2 -d ' ' | sort -ru | head -n 1) \
12- && udpkg -i /tmp/driver.udeb && depmod && modprobe {{driver['module']}}
13+d-i preseed/early_command string \
14+ echo -en '{{''.join(['\\x%x' % x for x in map(ord, str(install_udeb))])}}' > /tmp/install_udeb.sh && \
15+ chmod +x /tmp/install_udeb.sh && \
16+ /tmp/install_udeb.sh
17
18 d-i apt-setup/local0/repository string deb {{driver['repository']}} trusty main
19 d-i apt-setup/local0/comment string {{driver['comment']}}
20-d-i apt-setup/local0/key string {{driver['key']}}
21+d-i apt-setup/local0/key string file:///tmp/maas-{{driver['package']}}/repo_key.gpg
22 {{endif}}
23 {{enddef}}
24
25@@ -56,3 +55,56 @@
26 {{endif}}
27 true
28 {{enddef}}
29+
30+{{def install_udeb}}
31+{{if third_party_drivers and driver}}
32+#!/usr/bin/env sh
33+
34+set -eu
35+
36+REPO={{driver['repository']}}
37+KERNEL_VERSION=`uname -r`
38+TMPDIR=/tmp/maas-{{driver['package']}}
39+mkdir $TMPDIR
40+
41+echo -en '{{''.join(['\\x%x' % x for x in map(ord, driver['key_binary'])])}}' > $TMPDIR/repo_key.gpg
42+
43+# Retrieve the Release file and verify it against the repository's key.
44+wget -O $TMPDIR/Release $REPO/dists/trusty/Release
45+wget -O $TMPDIR/Release.gpg $REPO/dists/trusty/Release.gpg
46+gpgv --keyring $TMPDIR/repo_key.gpg $TMPDIR/Release.gpg $TMPDIR/Release
47+
48+# Retrieve the Packages file and verify it against the Releases file.
49+wget -O $TMPDIR/Packages $REPO/dists/trusty/main/debian-installer/binary-amd64/Packages
50+expected_sha256=`sed -n -e '/^SHA256:$/,$p' $TMPDIR/Release | grep 'main/debian-installer/binary-amd64/Packages$' | cut -f 2 -d ' '`
51+actual_sha256=`sha256sum $TMPDIR/Packages | cut -f 1 -d ' '`
52+if [ "$expected_sha256" != "$actual_sha256" ]
53+then
54+ echo "Packages sha256 value mismatch."
55+ echo "expected: $expected_sha256, actual: $actual_sha256"
56+ exit 1
57+fi
58+
59+# Retrieve the udeb and verify it against the Packages file. This method
60+# of locating the sha256 sum for the udeb within the Packages file
61+# relies on the SHA256 line coming after the Filename line in the udeb's
62+# record in the Packages file.
63+filename=`grep ^Filename.*$KERNEL_VERSION $TMPDIR/Packages | cut -f 2 -d ' ' | sort -ru | head -n 1`
64+wget -O $TMPDIR/driver.udeb $REPO/$filename
65+basename=${filename##*/}
66+sed_expression="/$basename"'$/,$p'
67+expected_udeb_sha256=`sed -n -e $sed_expression $TMPDIR/Packages | grep ^SHA256: | cut -f 2 -d ' ' | head -n 1`
68+actual_udeb_sha256=`sha256sum $TMPDIR/driver.udeb | cut -f 1 -d ' '`
69+if [ "$expected_udeb_sha256" != "$actual_udeb_sha256" ]
70+then
71+ echo "udeb sha256 value mismatch."
72+ echo "expected: $expected_udeb_sha256, actual: $actual_udeb_sha256"
73+ exit 1
74+fi
75+
76+# Install the udeb and load the kernel module.
77+udpkg -i $TMPDIR/driver.udeb
78+depmod
79+modprobe {{driver['module']}}
80+{{endif}}
81+{{enddef}}
82
83=== modified file 'etc/maas/drivers.yaml'
84--- etc/maas/drivers.yaml 2014-04-10 20:07:41 +0000
85+++ etc/maas/drivers.yaml 2014-04-14 21:33:28 +0000
86@@ -1,7 +1,14 @@
87 drivers:
88 - blacklist: ahci
89 comment: HPVSA driver
90- key: http://keyserver.ubuntu.com/pks/lookup?search=0x509C5B70C2755E20F737DC27933312C3CF700356&op=get
91+ key_binary: !!binary |
92+ mI0EUXBVgAEEAMMuSjjc/OYlR76O9dRcMBipKp5/gTUoYovm0dxVDb+JnyOqsVlad+pZbUhTiQnl
93+ ogoZdbt4i/yffP/8TydipLd3emw6xjyN5wkhGZfVvnslopZcPsjvXIdnC1sSbdWe/NwOLGn9svc+
94+ FimbIrwvVx4sL/Z50QK1/4Cu6Gaxh531ABEBAAG0I0xhdW5jaHBhZCBQUEEgZm9yIEhQIElTUyBM
95+ aW51eCBUZWFtiLgEEwECACIFAlFwVYACGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEJMz
96+ EsPPcANWfQ8D/RYq9u2QfyQej+2r7nGlETXl79xvaFzqwfkzuYwrUnxDuxUGTZz+yrLRBdPmYN4y
97+ d7neu+9NsDAoHkpL5wyCgC7FSVSXZOT7PsMvj5IncQQc4ktnBp6vKTdfoQ1bIGaQEPrbliz6whxP
98+ YfNe1eT+RyB4YP5/lclGsj+dtOdLzKh9sAIAAw==
99 modaliases:
100 - 'pci:v00001590d00000047sv00001590sd00000047bc*sc*i*'
101 - 'pci:v00001590d00000045sv00001590sd00000045bc*sc*i*'
102
103=== modified file 'src/maasserver/tests/test_third_party_drivers.py'
104--- src/maasserver/tests/test_third_party_drivers.py 2014-04-10 20:07:41 +0000
105+++ src/maasserver/tests/test_third_party_drivers.py 2014-04-14 21:33:28 +0000
106@@ -110,35 +110,14 @@
107
108 class TestDriversConfig(MAASTestCase):
109
110- production_config = {
111- 'drivers': [
112- {
113- 'blacklist': 'ahci',
114- 'comment': 'HPVSA driver',
115- 'key': ('http://keyserver.ubuntu.com/pks/lookup?search='
116- '0x509C5B70C2755E20F737DC27933312C3CF700356&op=get'),
117- 'modaliases': [
118- 'pci:v00001590d00000047sv00001590sd00000047bc*sc*i*',
119- 'pci:v00001590d00000045sv00001590sd00000045bc*sc*i*',
120- 'pci:v00008086d00001D04sv00001590sd00000048bc*sc*i*',
121- 'pci:v00008086d00008C04sv00001590sd00000084bc*sc*i*',
122- 'pci:v00008086d00008C06sv00001590sd00000084bc*sc*i*',
123- 'pci:v00008086d00001C04sv00001590sd0000006Cbc*sc*i*',
124- ],
125- 'module': 'hpvsa',
126- 'repository':
127- 'http://ppa.launchpad.net/hp-iss-team/hpvsa-update/ubuntu',
128- 'package': 'hpvsa',
129- },
130- ]
131- }
132-
133 def test_get_defaults_returns_empty_drivers_list(self):
134 observed = DriversConfig.get_defaults()
135 self.assertEqual({'drivers': []}, observed)
136
137 def test_load_from_yaml(self):
138 filename = os.path.join(root, "etc", "maas", "drivers.yaml")
139- self.assertEqual(
140- self.production_config,
141- DriversConfig.load(filename))
142+ for entry in DriversConfig.load(filename)['drivers']:
143+ self.assertItemsEqual(
144+ ['blacklist', 'comment', 'key_binary', 'modaliases',
145+ 'module', 'repository', 'package'],
146+ entry)
147
148=== modified file 'src/maasserver/third_party_drivers.py'
149--- src/maasserver/third_party_drivers.py 2014-04-10 20:07:41 +0000
150+++ src/maasserver/third_party_drivers.py 2014-04-14 21:33:28 +0000
151@@ -3,8 +3,7 @@
152
153 """Third party driver support.
154
155-The current implementation is limited in a number of ways.
156-
157+The current implementation is limited in a number of ways:
158 - Third party driver locations are currently hardcoded. Eventually,
159 they will be fetched from a stream.
160 - Only one third party driver can be matched per system.
161@@ -55,7 +54,31 @@
162 comment - A comment string that will be added to the sources.list file
163 on the target.
164
165-key - The URL to the public key for the repository.
166+key_binary - The public key for the repository in binary. Starting with a
167+binary gpg key file (NOT ascii armored) containing the key for a repository,
168+you can generate the key binary string like this:
169+
170+>>>> import yaml
171+>>>> key_text = open('my_key.gpg').read()
172+>>>> print yaml.dump(key_text)
173+
174+NOTE: If you start off with an ascii armored key, you can convert it into
175+a binary key by importing it into a gpg keyring, then exporting it into
176+a file without using -a/--armor.
177+
178+You can inspect a key from drivers.yaml by dumping it back into a file
179+and using gpg to manipulate it:
180+
181+>>> import yaml
182+>>> drivers_config = yaml.load(open('etc/maas/drivers.yaml').read())
183+>>> drivers_list = drivers_config['drivers']
184+>>> first_driver = drivers_list[0]
185+>>> open('some_key.gpg', 'w').write(first_driver['key_binary'])
186+
187+$ gpg --import -n some_key.gpg
188+gpg: key CF700356: "Launchpad PPA for Some Driver" not changed
189+gpg: Total number processed: 1
190+gpg: unchanged: 1
191
192 modaliases - The list of modaliases patterns to match when deciding when
193 to use this driver. MAAS collects modalias strings for nodes during
194@@ -78,7 +101,7 @@
195
196 blacklist = String()
197 comment = String()
198- key = String()
199+ key_binary = String()
200 modaliases = ForEach(String)
201 module = String()
202 package = String()