Merge ~teknoraver/snappy-hwe-snaps/+git/wifi-ap:wpapass into ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:master

Proposed by Matteo Croce
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)
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

Description of the change

Generate automatically a WPA password

To post a comment you must log in.
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

change looks good however the code-layout could be improved for readability.

review: Needs Fixing (code)
Revision history for this message
Simon Fels (morphis) :
review: Needs Fixing
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

comments inline

review: Needs Fixing (code)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

ack

review: Approve (code)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
review: Needs Fixing
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) wrote :

LGTM

review: Approve
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/.spread-reuse.22327.yaml b/.spread-reuse.22327.yaml
0new file mode 1006440new file mode 100644
index 0000000..f54942f
--- /dev/null
+++ b/.spread-reuse.22327.yaml
@@ -0,0 +1,9 @@
1backends:
2 qemu:
3 systems:
4 - ubuntu-core-16:
5 username: test
6 password: test
7 address: localhost:59377
8 data:
9 pid: 22341
diff --git a/cmd/client/cmd_wizard.go b/cmd/client/cmd_wizard.go
index a8b9bb2..41dd538 100644
--- a/cmd/client/cmd_wizard.go
+++ b/cmd/client/cmd_wizard.go
@@ -18,9 +18,11 @@ package main
18import (18import (
19 "bufio"19 "bufio"
20 "bytes"20 "bytes"
21 "encoding/base64"
21 "encoding/json"22 "encoding/json"
22 "fmt"23 "fmt"
23 "log"24 "log"
25 "math/rand"
24 "net"26 "net"
25 "net/http"27 "net/http"
26 "os"28 "os"
@@ -28,8 +30,11 @@ import (
28 "regexp"30 "regexp"
29 "strconv"31 "strconv"
30 "strings"32 "strings"
33 "time"
31)34)
3235
36const DefaultPassworthLength = 16
37
33type wizardStep func(map[string]interface{}, *bufio.Reader, bool) error38type wizardStep func(map[string]interface{}, *bufio.Reader, bool) error
3439
35// Go stores both IPv4 and IPv6 as [16]byte40// Go stores both IPv4 and IPv6 as [16]byte
@@ -40,7 +45,7 @@ const ipv4Offset = net.IPv6len - net.IPv4len
40var defaultIp = net.IPv4(10, 0, 60, 1)45var defaultIp = net.IPv4(10, 0, 60, 1)
4146
42// Utility function to read input and strip the trailing \n47// Utility function to read input and strip the trailing \n
43func readUserInput(reader *bufio.Reader) string {48var readUserInput = func (reader *bufio.Reader) string {
44 ret, err := reader.ReadString('\n')49 ret, err := reader.ReadString('\n')
45 if err != nil {50 if err != nil {
46 panic(err)51 panic(err)
@@ -98,6 +103,22 @@ func findFreeSubnet(startIp net.IP) (net.IP, error) {
98 return curIp, nil103 return curIp, nil
99}104}
100105
106func generatePassword(length int) string {
107 // base64 produces 4 byte for every 3 byte of input, rounded up
108 password := make([]byte, length / 4 * 3 + 3)
109 rand.Read(password)
110 return base64.StdEncoding.EncodeToString(password)[:length]
111}
112
113func askForPassword(reader *bufio.Reader) (string, error) {
114 fmt.Print("Please enter the WPA2 passphrase: ")
115 key := readUserInput(reader)
116 if len(key) < 8 || len(key) > 63 {
117 return "", fmt.Errorf("WPA2 passphrase must be between 8 and 63 characters")
118 }
119 return key, nil
120}
121
101var allSteps = [...]wizardStep{122var allSteps = [...]wizardStep{
102 // determine the WiFi interface123 // determine the WiFi interface
103 func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error {124 func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error {
@@ -150,7 +171,7 @@ var allSteps = [...]wizardStep{
150 // Select WiFi encryption type171 // Select WiFi encryption type
151 func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error {172 func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error {
152 if nonInteractive {173 if nonInteractive {
153 configuration["wifi.security"] = "open"174 configuration["wifi.security"] = "wpa2"
154 return nil175 return nil
155 }176 }
156177
@@ -172,12 +193,18 @@ var allSteps = [...]wizardStep{
172 if configuration["wifi.security"] == "open" {193 if configuration["wifi.security"] == "open" {
173 return nil194 return nil
174 }195 }
175 fmt.Print("Please enter the WPA2 passphrase: ")196 if nonInteractive {
176 key := readUserInput(reader)197 // Generate a random 16 characters alphanumeric password
177 if len(key) < 8 || len(key) > 63 {198 configuration["wifi.security-passphrase"] = generatePassword(DefaultPassworthLength)
178 return fmt.Errorf("WPA2 passphrase must be between 8 and 63 characters")199 return nil
200 }
201
202 // Ask the user for a valid password (min 8, max 63 chars)
203 if password, err := askForPassword(reader); err == nil {
204 configuration["wifi.security-passphrase"] = password
205 } else {
206 return err
179 }207 }
180 configuration["wifi.security-passphrase"] = key
181208
182 return nil209 return nil
183 },210 },
@@ -423,6 +450,8 @@ type wizardCommand struct {
423}450}
424451
425func (cmd *wizardCommand) Execute(args []string) error {452func (cmd *wizardCommand) Execute(args []string) error {
453 rand.Seed(time.Now().UnixNano())
454
426 // Setup some sane default values, we don't ask the user for everything455 // Setup some sane default values, we don't ask the user for everything
427 configuration := make(map[string]interface{})456 configuration := make(map[string]interface{})
428457
diff --git a/cmd/client/cmd_wizard_test.go b/cmd/client/cmd_wizard_test.go
429new file mode 100644458new file mode 100644
index 0000000..7bb7391
--- /dev/null
+++ b/cmd/client/cmd_wizard_test.go
@@ -0,0 +1,62 @@
1//
2// Copyright (C) 2017 Canonical Ltd
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License version 3 as
6// published by the Free Software Foundation.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16package main
17
18import (
19 "bufio"
20 "math/rand"
21 "strconv"
22 "testing"
23 "time"
24
25 . "gopkg.in/check.v1"
26)
27
28// gopkg.in/check.v1 stuff
29func TestWizard(t *testing.T) { TestingT(t) }
30
31type WizardSuite struct{}
32
33var _ = Suite(&WizardSuite{})
34
35func (s *WizardSuite) SetUpTest(c *C) {
36 rand.Seed(time.Now().UnixNano())
37}
38
39func mockUserInput(reply string) func (reader *bufio.Reader) string {
40 return func (_ *bufio.Reader) string {
41 return reply
42 }
43}
44
45var passRegExp = "[a-zA-Z0-9+/]{"+strconv.Itoa(DefaultPassworthLength)+"}"
46
47func (s *WizardSuite) TestPasswordGeneration(c *C) {
48 password := generatePassword(DefaultPassworthLength)
49 c.Assert(password, HasLen, DefaultPassworthLength)
50 c.Assert(password, Matches, passRegExp)
51
52 readUserInput = mockUserInput("short")
53 password, err := askForPassword(nil)
54 c.Assert(err, NotNil)
55
56 readUserInput = mockUserInput("4/Valid+Passw0rd")
57 password, err = askForPassword(nil)
58 c.Assert(err, IsNil)
59
60 c.Assert(password, HasLen, DefaultPassworthLength)
61 c.Assert(password, Matches, passRegExp)
62}
diff --git a/docs/basic-ap-setup.md b/docs/basic-ap-setup.md
index b535699..6fe0a09 100644
--- a/docs/basic-ap-setup.md
+++ b/docs/basic-ap-setup.md
@@ -13,6 +13,14 @@ $ wifi-ap.status
1313
14if the automatic configuration was successful and the access point is already active.14if the automatic configuration was successful and the access point is already active.
1515
16By default the automatic wizard, which runs when the wifi-ap snap is installed,
17will choose secure enough default password and will enable WPA2-PSK security.
18You can find the selected password when logged into
19the system the wifi-ap snap installed on by running the command:
20```
21$ sudo wifi-ap.config get wifi.security-passphrase
22```
23
16To enable the WiFi access point manually after the snap was installed and all plugs and slots are connected run the following command:24To enable the WiFi access point manually after the snap was installed and all plugs and slots are connected run the following command:
1725
18```26```
diff --git a/docs/installation.md b/docs/installation.md
index 720cb19..720e9ba 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -41,8 +41,8 @@ $ snap connect wifi-ap:network-manager network-manager:service
41|------|-------|41|------|-------|
42| **WiFi SSID** | Ubuntu |42| **WiFi SSID** | Ubuntu |
43| **WiFi Interface mode** | direct |43| **WiFi Interface mode** | direct |
44| **WiFi Security** | open |44| **WiFi Security** | wpa2 |
45| **WiFi Security Passphrase ** | |45| **WiFi Security Passphrase ** | Randomly chosen |
46| **WiFi Channel** | 6 |46| **WiFi Channel** | 6 |
47| **WiFi Network Interface** | wlan0 |47| **WiFi Network Interface** | wlan0 |
48| **WiFi Address** | 192.168.7.1 |48| **WiFi Address** | 192.168.7.1 |
diff --git a/tests/lib/restore-each.sh b/tests/lib/restore-each.sh
index b0d1902..0cfc960 100644
--- a/tests/lib/restore-each.sh
+++ b/tests/lib/restore-each.sh
@@ -31,6 +31,10 @@ netplan generate
31netplan apply31netplan apply
3232
33# remove and reinsert the module to refresh all the wifi network settings33# remove and reinsert the module to refresh all the wifi network settings
34pkill wpa_supplicant || true
35while pidof wpa_supplicant; do
36 sleep .5
37done
34rmmod mac80211_hwsim || true38rmmod mac80211_hwsim || true
35modprobe mac80211_hwsim radios=239modprobe mac80211_hwsim radios=2
36wait_until_interface_is_available wlan040wait_until_interface_is_available wlan0
diff --git a/tests/lib/utilities.sh b/tests/lib/utilities.sh
index 83f2e9e..9190e21 100644
--- a/tests/lib/utilities.sh
+++ b/tests/lib/utilities.sh
@@ -45,3 +45,25 @@ install_snap_under_test() {
45 snap connect wifi-ap:firewall-control core45 snap connect wifi-ap:firewall-control core
46 fi46 fi
47}47}
48
49# Connects to a WiFi network
50# args1: interface to use
51connect_to_wifi() {
52 local enc ssid pass
53
54 enc=$(/snap/bin/wifi-ap.config get wifi.security)
55 ssid=$(/snap/bin/wifi-ap.config get wifi.ssid)
56 if [ "$enc" = open ]; then
57 iw "$1" connect "$ssid"
58 else
59 pass=$(/snap/bin/wifi-ap.config get wifi.security-passphrase)
60 wpa_passphrase "$ssid" "$pass" >/tmp/wpa.conf
61 wpa_supplicant -B -c/tmp/wpa.conf -i"$1"
62
63 # Need to wait for a full scan and WPA2 handshake
64 for i in $(seq 60); do
65 iw dev "$1" link |fgrep -xq 'Not connected.' || break
66 sleep 1
67 done
68 fi
69}
diff --git a/tests/main/conf-wizard-auto-at-boot/task.yaml b/tests/main/conf-wizard-auto-at-boot/task.yaml
index b042097..13d5394 100644
--- a/tests/main/conf-wizard-auto-at-boot/task.yaml
+++ b/tests/main/conf-wizard-auto-at-boot/task.yaml
@@ -5,7 +5,9 @@ execute: |
5 test "$(/snap/bin/wifi-ap.config get disabled)" = false5 test "$(/snap/bin/wifi-ap.config get disabled)" = false
66
7 test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan07 test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan0
8 test "$(/snap/bin/wifi-ap.config get wifi.security)" = open8 test "$(/snap/bin/wifi-ap.config get wifi.security)" = wpa2
9 # Random 16 characters password, plus an ending line
10 test "$(/snap/bin/wifi-ap.config get wifi.security-passphrase |wc -c)" -eq 17
9 test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu11 test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu
10 test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.112 test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.1
1113
diff --git a/tests/main/conf-wizard-auto/task.yaml b/tests/main/conf-wizard-auto/task.yaml
12deleted file mode 10064414deleted file mode 100644
index ae6219c..0000000
--- a/tests/main/conf-wizard-auto/task.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
1summary: Verify that the automatic wizard works
2
3execute: |
4 # The automatic wizard was already started
5
6 # Check that we get good default values
7 test "$(/snap/bin/wifi-ap.config get disabled)" = false
8
9 test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan0
10 test "$(/snap/bin/wifi-ap.config get wifi.security)" = open
11 test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu
12 test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.1
13
14 test "$(/snap/bin/wifi-ap.config get dhcp.range-start)" = 10.0.60.2
15 test "$(/snap/bin/wifi-ap.config get dhcp.range-stop)" = 10.0.60.199
16
17 default_route=$(ip route |awk '/default/{print$5}')
18 if [ -n "$default_route" ]; then
19 test "$(/snap/bin/wifi-ap.config get share.disabled)" = false
20 test "$(/snap/bin/wifi-ap.config get share.network-interface)" = "$default_route"
21 else
22 test "$(/snap/bin/wifi-ap.config get share.disabled)" = true
23 fi
diff --git a/tests/main/default-conf-brings-up-ap/task.yaml b/tests/main/default-conf-brings-up-ap/task.yaml
index 6777c8d..28b9363 100644
--- a/tests/main/default-conf-brings-up-ap/task.yaml
+++ b/tests/main/default-conf-brings-up-ap/task.yaml
@@ -14,12 +14,11 @@ execute: |
14 # There should be only a single network14 # There should be only a single network
15 network_count=`/snap/bin/wireless-tools.iw dev wlan1 scan | grep -c 'SSID: Ubuntu'`15 network_count=`/snap/bin/wireless-tools.iw dev wlan1 scan | grep -c 'SSID: Ubuntu'`
16 test $network_count -eq 116 test $network_count -eq 1
17 # The AP should not be secured by default17 # The AP should not be secured
18 ! /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'WPA:'18 /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'RSN:'
19 ! /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'RSN:'
2019
21 # Verify we can associate with the AP20 # Verify we can associate with the AP
22 /snap/bin/wireless-tools.iw wlan1 connect Ubuntu21 connect_to_wifi wlan1
23 /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'22 /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'
2423
25 # And we should get an IP address assigned over DHCP24 # And we should get an IP address assigned over DHCP
diff --git a/tests/main/stress-ap-status-control/task.yaml b/tests/main/stress-ap-status-control/task.yaml
index 89ded92..7f3b4cf 100644
--- a/tests/main/stress-ap-status-control/task.yaml
+++ b/tests/main/stress-ap-status-control/task.yaml
@@ -10,6 +10,8 @@ prepare: |
10 snap connect wireless-tools:network-control core10 snap connect wireless-tools:network-control core
1111
12execute: |12execute: |
13 . $TESTSLIB/utilities.sh
14
13 # Bring up the access point first15 # Bring up the access point first
14 /snap/bin/wifi-ap.config set disabled=false16 /snap/bin/wifi-ap.config set disabled=false
15 until /snap/bin/wifi-ap.status | grep "ap.active: true" ; do17 until /snap/bin/wifi-ap.status | grep "ap.active: true" ; do
@@ -60,8 +62,8 @@ execute: |
60 test $found_ap -eq 162 test $found_ap -eq 1
6163
62 # Verify we can associate with the AP64 # Verify we can associate with the AP
63 sudo /snap/bin/wireless-tools.iw wlan1 connect Ubuntu65 connect_to_wifi wlan1
64 sudo /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'66 /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'
6567
66 # We should only have one hostapd and one dnsmasq process at this time68 # We should only have one hostapd and one dnsmasq process at this time
67 # (we have to ignore the grep'ing process as otherwise we get a count of 2)69 # (we have to ignore the grep'ing process as otherwise we get a count of 2)
diff --git a/tests/main/utf8-ssid/task.yaml b/tests/main/utf8-ssid/task.yaml
index ad9e594..b4f53ae 100644
--- a/tests/main/utf8-ssid/task.yaml
+++ b/tests/main/utf8-ssid/task.yaml
@@ -43,6 +43,5 @@ execute: |
43 test $network_count -eq 143 test $network_count -eq 1
4444
45 # Verify we can associate with the AP45 # Verify we can associate with the AP
46 /snap/bin/wireless-tools.iw wlan1 connect 'Ubuntu👍'46 connect_to_wifi wlan1
47 /snap/bin/wireless-tools.iw dev wlan1 link | fgrep 'SSID: Ubuntu\xf0\x9f\x91\x8d'47 /snap/bin/wireless-tools.iw dev wlan1 link | fgrep 'SSID: Ubuntu\xf0\x9f\x91\x8d'
48

Subscribers

People subscribed via source and target branches

to all changes: