Skip to content

Commit

Permalink
Update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
jcapona committed Sep 5, 2024
1 parent ab3080d commit 0cfacac
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 52 deletions.
34 changes: 34 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,37 @@ About

Application that configures a pi-top using an USB drive, installing offline updates
and setting up locales, language and wi-fi networks.

When a USB drive is plugged to the system with a file called `pi-top-usb-setup.tar.gz`,
a udev rule starts a systemd service that extracts the tarball and runs the setup script.

The setup script updates the system using a local apt repository with the files in the USB drive,
and the uses a JSON file to set the locales, language, keyboard layout and wi-fi network.

--------
JSON
--------

Format of the JSON file:

```json
{
"language": "en_GB",
"country": "GB",
"time_zone": "Europe/London",
"keyboard_layout": ["gb", null],
"email": "my@email.com",
"network": {
"ssid": "this-is-a-ssid",
"authentication": {
"type": "WPA_ENTERPRISE",
"data": {
"authentication": "PEAP",
"anonymous_identity": "this-is-an-anonymous-identity",
"username": "this-is-a-username",
"inner_authentication": "MSCHAPv2",
"password": "this-is-a-password",
},
},
},
}
73 changes: 29 additions & 44 deletions pi_top_usb_setup/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
logger = logging.getLogger(__name__)


CERT_FOLDER = "/usr/local/share/ca-certificates/"
CERT_FOLDER = "/usr/local/share/ca-certificates"

#################################
# Enums
Expand Down Expand Up @@ -77,10 +77,6 @@ def cleanup(cls, **kwargs) -> dict:
}


def generate_filename(id: str, prefix: str, extension: str) -> str:
return f"{CERT_FOLDER}/PT{id}-{prefix}.{extension}"


@dataclass
class File:
filename: str
Expand Down Expand Up @@ -111,7 +107,6 @@ def save(self):
#################################
@dataclass
class PWDAuthentication(NetworkBase):
id: str
username: str
password: Optional[str] = None

Expand All @@ -121,9 +116,9 @@ def from_kwargs(cls, **kwargs):
return PWDAuthentication(**cls.cleanup(**kwargs))

def to_nmcli(self) -> str:
response = f"key-mgmt wpa-eap \
response = f'key-mgmt wpa-eap \
802-1x.eap pwd \
802-1x.identity {self.username}"
802-1x.identity "{self.username}"'
if self.password:
response += f' 802-1x.password "{self.password}"'
return response
Expand All @@ -140,7 +135,6 @@ def to_wpasupplicant_conf(self) -> List:

@dataclass
class TLSAuthentication(NetworkBase):
id: str
identity: str
user_private_key: File
domain: Optional[str] = None
Expand All @@ -166,19 +160,18 @@ def from_kwargs(cls, **kwargs):
return TLSAuthentication(**cls.cleanup(**args))

def to_nmcli(self) -> str:
response = f"802-11-wireless-security.key-mgmt wpa-eap \
response = f'802-11-wireless-security.key-mgmt wpa-eap \
802-1x.eap tls \
802-1x.identity {self.identity} \
802-1x.private-key {self.user_private_key.path}"
802-1x.identity "{self.identity}" \
802-1x.private-key "{self.user_private_key.path}"'
if self.domain:
response += f" 802-1x.domain-suffix-match {self.domain}"
response += f' 802-1x.domain-suffix-match "{self.domain}"'
if self.ca_cert:
response += f" 802-1x.ca-cert {self.ca_cert.path}"
response += f' 802-1x.ca-cert "{self.ca_cert.path}"'
if self.ca_cert_password:
response += f' 802-1x.ca-cert-password "{self.ca_cert_password}"'
# CHECK: REQUIRED?????
if self.user_cert:
response += f" 802-1x.client-cert {self.user_cert.path}"
response += f' 802-1x.client-cert "{self.user_cert.path}"'
if self.user_cert_password:
response += f' 802-1x.client-cert-password "{self.user_cert_password}"'
if self.user_private_key_password:
Expand Down Expand Up @@ -211,10 +204,9 @@ def to_wpasupplicant_conf(self) -> List:

@dataclass
class TTLSAuthentication(NetworkBase):
id: str
anonymous_identity: str
username: str
inner_authentication: TTLSInnerAuthentication
anonymous_identity: str
ca_cert: Optional[File] = None
ca_cert_password: Optional[str] = None
password: Optional[str] = None
Expand All @@ -229,16 +221,18 @@ def from_kwargs(cls, **kwargs):
if "ca_cert" in args:
args["ca_cert"] = File.from_dict(args["ca_cert"])
args["ca_cert"].save()
if "anonymous_identity" not in args:
args["anonymous_identity"] = ""
return TTLSAuthentication(**args)

def to_nmcli(self) -> str:
response = f"802-11-wireless-security.key-mgmt wpa-eap \
response = f'802-11-wireless-security.key-mgmt wpa-eap \
802-1x.eap ttls \
802-1x.anonymous-identity {self.anonymous_identity} \
802-1x.identity {self.username} \
802-1x.phase2-auth {self.inner_authentication.name}"
802-1x.anonymous-identity "{self.anonymous_identity}" \
802-1x.identity "{self.username}" \
802-1x.phase2-auth {self.inner_authentication.name}'
if self.ca_cert:
response += f" 802-1x.ca-cert {self.ca_cert.path}"
response += f' 802-1x.ca-cert "{self.ca_cert.path}"'
if self.ca_cert_password:
response += f' 802-1x.ca-cert-password "{self.ca_cert_password}"'
if self.password:
Expand All @@ -264,7 +258,6 @@ def to_wpasupplicant_conf(self) -> List:

@dataclass
class PEAPAuthentication(NetworkBase):
id: str
username: str
inner_authentication: PEAPInnerAuthentication = PEAPInnerAuthentication.MSCHAPv2
peap_version: PEAPVersion = PEAPVersion.AUTOMATIC
Expand All @@ -289,18 +282,18 @@ def from_kwargs(cls, **kwargs):
return PEAPAuthentication(**args)

def to_nmcli(self) -> str:
response = f"802-11-wireless-security.key-mgmt wpa-eap \
response = f'802-11-wireless-security.key-mgmt wpa-eap \
802-1x.eap peap \
802-1x.identity {self.username} \
802-1x.phase2-auth {self.inner_authentication.name}"
802-1x.identity "{self.username}" \
802-1x.phase2-auth {self.inner_authentication.name}'
if self.anonymous_identity:
response += f" 802-1x.anonymous-identity {self.anonymous_identity}"
response += f' 802-1x.anonymous-identity "{self.anonymous_identity}"'
if self.peap_version != PEAPVersion.AUTOMATIC:
response += f" 802-1x.phase1-peapver {self.peap_version.value}"
if self.domain:
response += f" 802-1x.domain-suffix-match {self.domain}"
response += f' 802-1x.domain-suffix-match "{self.domain}"'
if self.ca_cert:
response += f" 802-1x.ca-cert {self.ca_cert.path}"
response += f' 802-1x.ca-cert {self.ca_cert.path}"'
if self.ca_cert_password:
response += f' 802-1x.ca-cert-password "{self.ca_cert_password}"'
if self.password:
Expand Down Expand Up @@ -333,7 +326,6 @@ def to_wpasupplicant_conf(self) -> List:
#################################
@dataclass
class WpaPersonal(NetworkBase):
id: str
password: str

def to_nmcli(self) -> str:
Expand All @@ -350,14 +342,13 @@ def to_wpasupplicant_conf(self) -> List:

@dataclass
class LEAP(NetworkBase):
id: str
username: str
password: Optional[str] = None

def to_nmcli(self) -> str:
response = f"802-11-wireless-security.auth-alg leap \
response = f'802-11-wireless-security.auth-alg leap \
802-11-wireless-security.key-mgmt ieee8021x \
802-11-wireless-security.leap-username {self.username}"
802-11-wireless-security.leap-username "{self.username}"'
if self.password:
response += f'802-11-wireless-security.leap-password "{self.password}"'
return response
Expand All @@ -373,9 +364,7 @@ def to_wpasupplicant_conf(self) -> List:
return response


@dataclass
class OWE(NetworkBase):
id: str
class OWE:

def to_nmcli(self) -> str:
return "802-11-wireless-security.key-mgmt OWE"
Expand All @@ -386,7 +375,6 @@ def to_wpasupplicant_conf(self) -> List:

@dataclass
class Open(NetworkBase):
id: str

def to_nmcli(self) -> str:
return ""
Expand Down Expand Up @@ -488,14 +476,14 @@ def connect(self):
def from_dict(cls, data: dict):
logger.info(f"--> Network: {data}")
return Network(
authentication=Network.get_authentication(data),
authentication=Network.get_authentication(data["authentication"]),
ssid=data["ssid"],
hidden=data.get("hidden", False),
)

@staticmethod
def get_authentication(
connection_data: dict,
auth_dict: dict,
) -> WpaPersonal | LEAP | OWE | WpaEnterprise:
lookup = {
WiFiSecurityEnum.LEAP: LEAP,
Expand All @@ -506,14 +494,11 @@ def get_authentication(
),
WiFiSecurityEnum.WPA_PERSONAL: WpaPersonal,
}
auth_dict = connection_data["authentication"]
wifi_security_enum = WiFiSecurityEnum[auth_dict["type"]]
wifi_security_class = lookup[wifi_security_enum]

assert callable(wifi_security_class)
return wifi_security_class(
**auth_dict.get("data", {}), id=Network.to_id(connection_data["ssid"])
)
return wifi_security_class(**auth_dict.get("data", {}))

def to_nmcli(self) -> str:
interface = "wlan0"
Expand Down
16 changes: 8 additions & 8 deletions tests/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt OWE',
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless.hidden yes 802-11-wireless-security.key-mgmt OWE', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" mode infra 802-11-wireless-security.key-mgmt wpa-psk 802-11-wireless-security.psk "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" key-mgmt wpa-eap 802-1x.eap pwd 802-1x.identity this-is-a-username 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap tls 802-1x.identity this-is-an-identity 802-1x.private-key /tmp/user.key', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap ttls 802-1x.anonymous-identity this-is-an-anonymous-identity 802-1x.identity this-is-a-username 802-1x.phase2-auth MSCHAPv2 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap peap 802-1x.identity this-is-a-username 802-1x.phase2-auth MSCHAPv2 802-1x.anonymous-identity this-is-an-anonymous-identity 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" key-mgmt wpa-eap 802-1x.eap pwd 802-1x.identity "this-is-a-username" 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap tls 802-1x.identity "this-is-an-identity" 802-1x.private-key "/tmp/user.key"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap ttls 802-1x.anonymous-identity "this-is-an-anonymous-identity" 802-1x.identity "this-is-a-username" 802-1x.phase2-auth MSCHAPv2 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap peap 802-1x.identity "this-is-a-username" 802-1x.phase2-auth MSCHAPv2 802-1x.anonymous-identity "this-is-an-anonymous-identity" 802-1x.password "this-is-a-password"', # noqa: E501
]

wpasupplicant_str_arr = [
Expand Down Expand Up @@ -140,19 +140,19 @@
'raspi-config nonint do_wifi_ssid_passphrase "this-is-a-ssid" "this-is-a-password" 0 0'
],
[
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" key-mgmt wpa-eap 802-1x.eap pwd 802-1x.identity this-is-a-username 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" key-mgmt wpa-eap 802-1x.eap pwd 802-1x.identity "this-is-a-username" 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection up "this-is-a-ssid"',
],
[
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap tls 802-1x.identity this-is-an-identity 802-1x.private-key /tmp/user.key', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap tls 802-1x.identity "this-is-an-identity" 802-1x.private-key "/tmp/user.key"', # noqa: E501
'nmcli connection up "this-is-a-ssid"',
],
[
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap ttls 802-1x.anonymous-identity this-is-an-anonymous-identity 802-1x.identity this-is-a-username 802-1x.phase2-auth MSCHAPv2 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap ttls 802-1x.anonymous-identity "this-is-an-anonymous-identity" 802-1x.identity "this-is-a-username" 802-1x.phase2-auth MSCHAPv2 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection up "this-is-a-ssid"',
],
[
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap peap 802-1x.identity this-is-a-username 802-1x.phase2-auth MSCHAPv2 802-1x.anonymous-identity this-is-an-anonymous-identity 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection add type wifi ifname wlan0 con-name "this-is-a-ssid" ssid "this-is-a-ssid" 802-11-wireless-security.key-mgmt wpa-eap 802-1x.eap peap 802-1x.identity "this-is-a-username" 802-1x.phase2-auth MSCHAPv2 802-1x.anonymous-identity "this-is-an-anonymous-identity" 802-1x.password "this-is-a-password"', # noqa: E501
'nmcli connection up "this-is-a-ssid"',
],
]
Expand Down

0 comments on commit 0cfacac

Please sign in to comment.