Merge ~teknoraver/snappy-hwe-snaps/+git/wifi-ap:wpapass into ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:master
- Git
- lp:~teknoraver/snappy-hwe-snaps/+git/wifi-ap
- wpapass
- Merge into master
Status: | Merged |
---|---|
Approved by: | Simon Fels |
Approved revision: | df8df420f7d8357995f0fa1a53fbac01e26223bf |
Merged at revision: | 67a49951c04daac96a28269bc257ea171b66d5e0 |
Proposed branch: | ~teknoraver/snappy-hwe-snaps/+git/wifi-ap:wpapass |
Merge into: | ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:master |
Diff against target: |
364 lines (+154/-41) 12 files modified
.spread-reuse.22327.yaml (+9/-0) cmd/client/cmd_wizard.go (+36/-7) cmd/client/cmd_wizard_test.go (+62/-0) dev/null (+0/-23) docs/basic-ap-setup.md (+8/-0) docs/installation.md (+2/-2) tests/lib/restore-each.sh (+4/-0) tests/lib/utilities.sh (+22/-0) tests/main/conf-wizard-auto-at-boot/task.yaml (+3/-1) tests/main/default-conf-brings-up-ap/task.yaml (+3/-4) tests/main/stress-ap-status-control/task.yaml (+4/-2) tests/main/utf8-ssid/task.yaml (+1/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
System Enablement Bot | continuous-integration | Approve | |
Simon Fels | Approve | ||
Konrad Zapałowicz (community) | code | Approve | |
Review via email: mp+320490@code.launchpad.net |
Commit message
Description of the change
Generate automatically a WPA password
Konrad Zapałowicz (kzapalowicz) wrote : | # |
Simon Fels (morphis) : | # |
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4cbb3342575
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Simon Fels (morphis) : | # |
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:c45afa2a5f0
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:27b09605c6c
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:dcc0cd5ee4f
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3681c8fefd3
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:38d5955936c
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Konrad Zapałowicz (kzapalowicz) wrote : | # |
comments inline
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:68688ee20c4
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:ad3ce5a317c
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Konrad Zapałowicz (kzapalowicz) wrote : | # |
ack
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:61aad44b337
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:779efba04ff
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Simon Fels (morphis) : | # |
Simon Fels (morphis) : | # |
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:e863357b550
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:18f3faa520d
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Simon Fels (morphis) : | # |
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3d4ff1d5564
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:1abdf717757
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | diff --git a/.spread-reuse.22327.yaml b/.spread-reuse.22327.yaml |
2 | new file mode 100644 |
3 | index 0000000..f54942f |
4 | --- /dev/null |
5 | +++ b/.spread-reuse.22327.yaml |
6 | @@ -0,0 +1,9 @@ |
7 | +backends: |
8 | + qemu: |
9 | + systems: |
10 | + - ubuntu-core-16: |
11 | + username: test |
12 | + password: test |
13 | + address: localhost:59377 |
14 | + data: |
15 | + pid: 22341 |
16 | diff --git a/cmd/client/cmd_wizard.go b/cmd/client/cmd_wizard.go |
17 | index a8b9bb2..41dd538 100644 |
18 | --- a/cmd/client/cmd_wizard.go |
19 | +++ b/cmd/client/cmd_wizard.go |
20 | @@ -18,9 +18,11 @@ package main |
21 | import ( |
22 | "bufio" |
23 | "bytes" |
24 | + "encoding/base64" |
25 | "encoding/json" |
26 | "fmt" |
27 | "log" |
28 | + "math/rand" |
29 | "net" |
30 | "net/http" |
31 | "os" |
32 | @@ -28,8 +30,11 @@ import ( |
33 | "regexp" |
34 | "strconv" |
35 | "strings" |
36 | + "time" |
37 | ) |
38 | |
39 | +const DefaultPassworthLength = 16 |
40 | + |
41 | type wizardStep func(map[string]interface{}, *bufio.Reader, bool) error |
42 | |
43 | // Go stores both IPv4 and IPv6 as [16]byte |
44 | @@ -40,7 +45,7 @@ const ipv4Offset = net.IPv6len - net.IPv4len |
45 | var defaultIp = net.IPv4(10, 0, 60, 1) |
46 | |
47 | // Utility function to read input and strip the trailing \n |
48 | -func readUserInput(reader *bufio.Reader) string { |
49 | +var readUserInput = func (reader *bufio.Reader) string { |
50 | ret, err := reader.ReadString('\n') |
51 | if err != nil { |
52 | panic(err) |
53 | @@ -98,6 +103,22 @@ func findFreeSubnet(startIp net.IP) (net.IP, error) { |
54 | return curIp, nil |
55 | } |
56 | |
57 | +func generatePassword(length int) string { |
58 | + // base64 produces 4 byte for every 3 byte of input, rounded up |
59 | + password := make([]byte, length / 4 * 3 + 3) |
60 | + rand.Read(password) |
61 | + return base64.StdEncoding.EncodeToString(password)[:length] |
62 | +} |
63 | + |
64 | +func askForPassword(reader *bufio.Reader) (string, error) { |
65 | + fmt.Print("Please enter the WPA2 passphrase: ") |
66 | + key := readUserInput(reader) |
67 | + if len(key) < 8 || len(key) > 63 { |
68 | + return "", fmt.Errorf("WPA2 passphrase must be between 8 and 63 characters") |
69 | + } |
70 | + return key, nil |
71 | +} |
72 | + |
73 | var allSteps = [...]wizardStep{ |
74 | // determine the WiFi interface |
75 | func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error { |
76 | @@ -150,7 +171,7 @@ var allSteps = [...]wizardStep{ |
77 | // Select WiFi encryption type |
78 | func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error { |
79 | if nonInteractive { |
80 | - configuration["wifi.security"] = "open" |
81 | + configuration["wifi.security"] = "wpa2" |
82 | return nil |
83 | } |
84 | |
85 | @@ -172,12 +193,18 @@ var allSteps = [...]wizardStep{ |
86 | if configuration["wifi.security"] == "open" { |
87 | return nil |
88 | } |
89 | - fmt.Print("Please enter the WPA2 passphrase: ") |
90 | - key := readUserInput(reader) |
91 | - if len(key) < 8 || len(key) > 63 { |
92 | - return fmt.Errorf("WPA2 passphrase must be between 8 and 63 characters") |
93 | + if nonInteractive { |
94 | + // Generate a random 16 characters alphanumeric password |
95 | + configuration["wifi.security-passphrase"] = generatePassword(DefaultPassworthLength) |
96 | + return nil |
97 | + } |
98 | + |
99 | + // Ask the user for a valid password (min 8, max 63 chars) |
100 | + if password, err := askForPassword(reader); err == nil { |
101 | + configuration["wifi.security-passphrase"] = password |
102 | + } else { |
103 | + return err |
104 | } |
105 | - configuration["wifi.security-passphrase"] = key |
106 | |
107 | return nil |
108 | }, |
109 | @@ -423,6 +450,8 @@ type wizardCommand struct { |
110 | } |
111 | |
112 | func (cmd *wizardCommand) Execute(args []string) error { |
113 | + rand.Seed(time.Now().UnixNano()) |
114 | + |
115 | // Setup some sane default values, we don't ask the user for everything |
116 | configuration := make(map[string]interface{}) |
117 | |
118 | diff --git a/cmd/client/cmd_wizard_test.go b/cmd/client/cmd_wizard_test.go |
119 | new file mode 100644 |
120 | index 0000000..7bb7391 |
121 | --- /dev/null |
122 | +++ b/cmd/client/cmd_wizard_test.go |
123 | @@ -0,0 +1,62 @@ |
124 | +// |
125 | +// Copyright (C) 2017 Canonical Ltd |
126 | +// |
127 | +// This program is free software: you can redistribute it and/or modify |
128 | +// it under the terms of the GNU General Public License version 3 as |
129 | +// published by the Free Software Foundation. |
130 | +// |
131 | +// This program is distributed in the hope that it will be useful, |
132 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
133 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
134 | +// GNU General Public License for more details. |
135 | +// |
136 | +// You should have received a copy of the GNU General Public License |
137 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
138 | + |
139 | +package main |
140 | + |
141 | +import ( |
142 | + "bufio" |
143 | + "math/rand" |
144 | + "strconv" |
145 | + "testing" |
146 | + "time" |
147 | + |
148 | + . "gopkg.in/check.v1" |
149 | +) |
150 | + |
151 | +// gopkg.in/check.v1 stuff |
152 | +func TestWizard(t *testing.T) { TestingT(t) } |
153 | + |
154 | +type WizardSuite struct{} |
155 | + |
156 | +var _ = Suite(&WizardSuite{}) |
157 | + |
158 | +func (s *WizardSuite) SetUpTest(c *C) { |
159 | + rand.Seed(time.Now().UnixNano()) |
160 | +} |
161 | + |
162 | +func mockUserInput(reply string) func (reader *bufio.Reader) string { |
163 | + return func (_ *bufio.Reader) string { |
164 | + return reply |
165 | + } |
166 | +} |
167 | + |
168 | +var passRegExp = "[a-zA-Z0-9+/]{"+strconv.Itoa(DefaultPassworthLength)+"}" |
169 | + |
170 | +func (s *WizardSuite) TestPasswordGeneration(c *C) { |
171 | + password := generatePassword(DefaultPassworthLength) |
172 | + c.Assert(password, HasLen, DefaultPassworthLength) |
173 | + c.Assert(password, Matches, passRegExp) |
174 | + |
175 | + readUserInput = mockUserInput("short") |
176 | + password, err := askForPassword(nil) |
177 | + c.Assert(err, NotNil) |
178 | + |
179 | + readUserInput = mockUserInput("4/Valid+Passw0rd") |
180 | + password, err = askForPassword(nil) |
181 | + c.Assert(err, IsNil) |
182 | + |
183 | + c.Assert(password, HasLen, DefaultPassworthLength) |
184 | + c.Assert(password, Matches, passRegExp) |
185 | +} |
186 | diff --git a/docs/basic-ap-setup.md b/docs/basic-ap-setup.md |
187 | index b535699..6fe0a09 100644 |
188 | --- a/docs/basic-ap-setup.md |
189 | +++ b/docs/basic-ap-setup.md |
190 | @@ -13,6 +13,14 @@ $ wifi-ap.status |
191 | |
192 | if the automatic configuration was successful and the access point is already active. |
193 | |
194 | +By default the automatic wizard, which runs when the wifi-ap snap is installed, |
195 | +will choose secure enough default password and will enable WPA2-PSK security. |
196 | +You can find the selected password when logged into |
197 | +the system the wifi-ap snap installed on by running the command: |
198 | +``` |
199 | +$ sudo wifi-ap.config get wifi.security-passphrase |
200 | +``` |
201 | + |
202 | To enable the WiFi access point manually after the snap was installed and all plugs and slots are connected run the following command: |
203 | |
204 | ``` |
205 | diff --git a/docs/installation.md b/docs/installation.md |
206 | index 720cb19..720e9ba 100644 |
207 | --- a/docs/installation.md |
208 | +++ b/docs/installation.md |
209 | @@ -41,8 +41,8 @@ $ snap connect wifi-ap:network-manager network-manager:service |
210 | |------|-------| |
211 | | **WiFi SSID** | Ubuntu | |
212 | | **WiFi Interface mode** | direct | |
213 | -| **WiFi Security** | open | |
214 | -| **WiFi Security Passphrase ** | | |
215 | +| **WiFi Security** | wpa2 | |
216 | +| **WiFi Security Passphrase ** | Randomly chosen | |
217 | | **WiFi Channel** | 6 | |
218 | | **WiFi Network Interface** | wlan0 | |
219 | | **WiFi Address** | 192.168.7.1 | |
220 | diff --git a/tests/lib/restore-each.sh b/tests/lib/restore-each.sh |
221 | index b0d1902..0cfc960 100644 |
222 | --- a/tests/lib/restore-each.sh |
223 | +++ b/tests/lib/restore-each.sh |
224 | @@ -31,6 +31,10 @@ netplan generate |
225 | netplan apply |
226 | |
227 | # remove and reinsert the module to refresh all the wifi network settings |
228 | +pkill wpa_supplicant || true |
229 | +while pidof wpa_supplicant; do |
230 | + sleep .5 |
231 | +done |
232 | rmmod mac80211_hwsim || true |
233 | modprobe mac80211_hwsim radios=2 |
234 | wait_until_interface_is_available wlan0 |
235 | diff --git a/tests/lib/utilities.sh b/tests/lib/utilities.sh |
236 | index 83f2e9e..9190e21 100644 |
237 | --- a/tests/lib/utilities.sh |
238 | +++ b/tests/lib/utilities.sh |
239 | @@ -45,3 +45,25 @@ install_snap_under_test() { |
240 | snap connect wifi-ap:firewall-control core |
241 | fi |
242 | } |
243 | + |
244 | +# Connects to a WiFi network |
245 | +# args1: interface to use |
246 | +connect_to_wifi() { |
247 | + local enc ssid pass |
248 | + |
249 | + enc=$(/snap/bin/wifi-ap.config get wifi.security) |
250 | + ssid=$(/snap/bin/wifi-ap.config get wifi.ssid) |
251 | + if [ "$enc" = open ]; then |
252 | + iw "$1" connect "$ssid" |
253 | + else |
254 | + pass=$(/snap/bin/wifi-ap.config get wifi.security-passphrase) |
255 | + wpa_passphrase "$ssid" "$pass" >/tmp/wpa.conf |
256 | + wpa_supplicant -B -c/tmp/wpa.conf -i"$1" |
257 | + |
258 | + # Need to wait for a full scan and WPA2 handshake |
259 | + for i in $(seq 60); do |
260 | + iw dev "$1" link |fgrep -xq 'Not connected.' || break |
261 | + sleep 1 |
262 | + done |
263 | + fi |
264 | +} |
265 | diff --git a/tests/main/conf-wizard-auto-at-boot/task.yaml b/tests/main/conf-wizard-auto-at-boot/task.yaml |
266 | index b042097..13d5394 100644 |
267 | --- a/tests/main/conf-wizard-auto-at-boot/task.yaml |
268 | +++ b/tests/main/conf-wizard-auto-at-boot/task.yaml |
269 | @@ -5,7 +5,9 @@ execute: | |
270 | test "$(/snap/bin/wifi-ap.config get disabled)" = false |
271 | |
272 | test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan0 |
273 | - test "$(/snap/bin/wifi-ap.config get wifi.security)" = open |
274 | + test "$(/snap/bin/wifi-ap.config get wifi.security)" = wpa2 |
275 | + # Random 16 characters password, plus an ending line |
276 | + test "$(/snap/bin/wifi-ap.config get wifi.security-passphrase |wc -c)" -eq 17 |
277 | test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu |
278 | test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.1 |
279 | |
280 | diff --git a/tests/main/conf-wizard-auto/task.yaml b/tests/main/conf-wizard-auto/task.yaml |
281 | deleted file mode 100644 |
282 | index ae6219c..0000000 |
283 | --- a/tests/main/conf-wizard-auto/task.yaml |
284 | +++ /dev/null |
285 | @@ -1,23 +0,0 @@ |
286 | -summary: Verify that the automatic wizard works |
287 | - |
288 | -execute: | |
289 | - # The automatic wizard was already started |
290 | - |
291 | - # Check that we get good default values |
292 | - test "$(/snap/bin/wifi-ap.config get disabled)" = false |
293 | - |
294 | - test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan0 |
295 | - test "$(/snap/bin/wifi-ap.config get wifi.security)" = open |
296 | - test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu |
297 | - test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.1 |
298 | - |
299 | - test "$(/snap/bin/wifi-ap.config get dhcp.range-start)" = 10.0.60.2 |
300 | - test "$(/snap/bin/wifi-ap.config get dhcp.range-stop)" = 10.0.60.199 |
301 | - |
302 | - default_route=$(ip route |awk '/default/{print$5}') |
303 | - if [ -n "$default_route" ]; then |
304 | - test "$(/snap/bin/wifi-ap.config get share.disabled)" = false |
305 | - test "$(/snap/bin/wifi-ap.config get share.network-interface)" = "$default_route" |
306 | - else |
307 | - test "$(/snap/bin/wifi-ap.config get share.disabled)" = true |
308 | - fi |
309 | diff --git a/tests/main/default-conf-brings-up-ap/task.yaml b/tests/main/default-conf-brings-up-ap/task.yaml |
310 | index 6777c8d..28b9363 100644 |
311 | --- a/tests/main/default-conf-brings-up-ap/task.yaml |
312 | +++ b/tests/main/default-conf-brings-up-ap/task.yaml |
313 | @@ -14,12 +14,11 @@ execute: | |
314 | # There should be only a single network |
315 | network_count=`/snap/bin/wireless-tools.iw dev wlan1 scan | grep -c 'SSID: Ubuntu'` |
316 | test $network_count -eq 1 |
317 | - # The AP should not be secured by default |
318 | - ! /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'WPA:' |
319 | - ! /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'RSN:' |
320 | + # The AP should not be secured |
321 | + /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'RSN:' |
322 | |
323 | # Verify we can associate with the AP |
324 | - /snap/bin/wireless-tools.iw wlan1 connect Ubuntu |
325 | + connect_to_wifi wlan1 |
326 | /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu' |
327 | |
328 | # And we should get an IP address assigned over DHCP |
329 | diff --git a/tests/main/stress-ap-status-control/task.yaml b/tests/main/stress-ap-status-control/task.yaml |
330 | index 89ded92..7f3b4cf 100644 |
331 | --- a/tests/main/stress-ap-status-control/task.yaml |
332 | +++ b/tests/main/stress-ap-status-control/task.yaml |
333 | @@ -10,6 +10,8 @@ prepare: | |
334 | snap connect wireless-tools:network-control core |
335 | |
336 | execute: | |
337 | + . $TESTSLIB/utilities.sh |
338 | + |
339 | # Bring up the access point first |
340 | /snap/bin/wifi-ap.config set disabled=false |
341 | until /snap/bin/wifi-ap.status | grep "ap.active: true" ; do |
342 | @@ -60,8 +62,8 @@ execute: | |
343 | test $found_ap -eq 1 |
344 | |
345 | # Verify we can associate with the AP |
346 | - sudo /snap/bin/wireless-tools.iw wlan1 connect Ubuntu |
347 | - sudo /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu' |
348 | + connect_to_wifi wlan1 |
349 | + /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu' |
350 | |
351 | # We should only have one hostapd and one dnsmasq process at this time |
352 | # (we have to ignore the grep'ing process as otherwise we get a count of 2) |
353 | diff --git a/tests/main/utf8-ssid/task.yaml b/tests/main/utf8-ssid/task.yaml |
354 | index ad9e594..b4f53ae 100644 |
355 | --- a/tests/main/utf8-ssid/task.yaml |
356 | +++ b/tests/main/utf8-ssid/task.yaml |
357 | @@ -43,6 +43,5 @@ execute: | |
358 | test $network_count -eq 1 |
359 | |
360 | # Verify we can associate with the AP |
361 | - /snap/bin/wireless-tools.iw wlan1 connect 'Ubuntu👍' |
362 | + connect_to_wifi wlan1 |
363 | /snap/bin/wireless-tools.iw dev wlan1 link | fgrep 'SSID: Ubuntu\xf0\x9f\x91\x8d' |
364 | - |
change looks good however the code-layout could be improved for readability.