mirror of
https://github.com/linux-system-roles/network.git
synced 2026-01-23 02:15:17 +00:00
Add support for 802.1x wired connections (EAP-TLS only)
Only EAP-TLS method is supported. Must use NetworkManager as the network_provider. Also fixed bug in do_connections_validate_nm() function.
This commit is contained in:
parent
d32f4e5a7b
commit
4af8f23955
22 changed files with 961 additions and 7 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -9,3 +9,4 @@
|
|||
/tests/tmp_merge_coveragerc
|
||||
/tests/total-*coveragedata
|
||||
/.tox
|
||||
/.vscode
|
||||
|
|
|
|||
69
README.md
69
README.md
|
|
@ -409,6 +409,58 @@ kernel and device, changing some features might not be supported.
|
|||
txvlan: yes|no # optional
|
||||
```
|
||||
|
||||
### `802.1x`
|
||||
|
||||
Configures 802.1x authentication for an interface.
|
||||
|
||||
Currently, NetworkManager is the only supported provider and EAP-TLS is the only supported EAP method.
|
||||
|
||||
SSL certificates and keys must be deployed on the host prior to running the role.
|
||||
|
||||
* `eap`
|
||||
|
||||
The allowed EAP method to be used when authenticating to the network with 802.1x.
|
||||
|
||||
Currently, `tls` is the default and the only accepted value.
|
||||
|
||||
* `identity` (required)
|
||||
|
||||
Identity string for EAP authentication methods.
|
||||
|
||||
* `private-key` (required)
|
||||
|
||||
Absolute path to the client's PEM or PKCS#12 encoded private key used for 802.1x authentication.
|
||||
|
||||
* `private-key-password`
|
||||
|
||||
Password to the private key specified in `private-key`.
|
||||
|
||||
* `private-key-password-flags`
|
||||
|
||||
List of flags to configure how the private key password is managed.
|
||||
|
||||
Multiple flags may be specified.
|
||||
|
||||
Valid flags are:
|
||||
- `none`
|
||||
- `agent-owned`
|
||||
- `not-saved`
|
||||
- `not-required`
|
||||
|
||||
See NetworkManager documentation on "Secret flag types" more details (`man 5 nm-settings`).
|
||||
|
||||
* `client-cert` (required)
|
||||
|
||||
Absolute path to the client's PEM encoded certificate used for 802.1x authentication.
|
||||
|
||||
* `ca-cert`
|
||||
|
||||
Absolute path to the PEM encoded certificate authority used to verify the EAP server.
|
||||
|
||||
* `system-ca-certs`
|
||||
|
||||
If set to `True`, NetworkManager will use the system's trusted ca certificates to verify the EAP server.
|
||||
|
||||
Examples of Options
|
||||
-------------------
|
||||
|
||||
|
|
@ -603,6 +655,23 @@ network_connections:
|
|||
rule_append_only: yes
|
||||
```
|
||||
|
||||
Configuring 802.1x:
|
||||
|
||||
```yaml
|
||||
network_connections:
|
||||
- name: eth0
|
||||
type: ethernet
|
||||
802.1x:
|
||||
identity: myhost
|
||||
eap: tls
|
||||
private-key: /etc/pki/tls/client.key
|
||||
# recommend vault encrypting the private key password
|
||||
# see https://docs.ansible.com/ansible/latest/user_guide/vault.html
|
||||
private-key-password: "p@55w0rD"
|
||||
client-cert: /etc/pki/tls/client.pem
|
||||
ca-cert: /etc/pki/tls/cacert.pem
|
||||
```
|
||||
|
||||
### Invalid and Wrong Configuration
|
||||
|
||||
The `network` role rejects invalid configurations. It is recommended to test the role
|
||||
|
|
|
|||
|
|
@ -20,16 +20,23 @@ network_provider_current: "{{
|
|||
# Default to the auto-detected value
|
||||
network_provider: "{{ network_provider_current }}"
|
||||
|
||||
# wpa_supplicant is required if any 802.1x connections are defined
|
||||
wpa_supplicant_required: "{{ network_connections |
|
||||
json_query('[*][\"802.1x\"]') | flatten | count > 0 }}"
|
||||
_network_packages_default_802_1x: ["{% if wpa_supplicant_required
|
||||
%}wpa_supplicant{% endif %}"]
|
||||
|
||||
# The python-gobject-base package depends on the python version and
|
||||
# distribution:
|
||||
# - python-gobject-base on RHEL7 (no python2-gobject-base :-/)
|
||||
# - python3-gobject-base on Fedora 28+
|
||||
_network_packages_default_gobject_packages: ["python{{
|
||||
ansible_python['version']['major'] | replace('2', '')}}-gobject-base"]
|
||||
|
||||
network_service_name_default_nm: NetworkManager
|
||||
network_packages_default_nm:
|
||||
- ethtool
|
||||
- NetworkManager
|
||||
- "python{{ ansible_python['version']['major'] | replace('2', '')
|
||||
}}-gobject-base"
|
||||
network_packages_default_nm: "{{ ['ethtool', 'NetworkManager']
|
||||
+ _network_packages_default_gobject_packages|select()|list()
|
||||
+ _network_packages_default_802_1x|select()|list()}}"
|
||||
|
||||
network_service_name_default_initscripts: network
|
||||
|
||||
|
|
|
|||
29
examples/eth-with-802-1x.yml
Normal file
29
examples/eth-with-802-1x.yml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
---
|
||||
- hosts: network-test
|
||||
vars:
|
||||
network_connections:
|
||||
- name: eth0
|
||||
type: ethernet
|
||||
802.1x:
|
||||
identity: myhost
|
||||
eap: tls
|
||||
private-key: /etc/pki/tls/client.key
|
||||
# recommend vault encrypting the private key password
|
||||
# see https://docs.ansible.com/ansible/latest/user_guide/vault.html
|
||||
private-key-password: "p@55w0rD"
|
||||
client-cert: /etc/pki/tls/client.pem
|
||||
ca-cert: /etc/pki/tls/cacert.pem
|
||||
|
||||
# certs have to be deployed first
|
||||
pre_tasks:
|
||||
- name: copy certs/keys for 802.1x auth
|
||||
copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/pki/tls/{{ item }}"
|
||||
with_items:
|
||||
- client.key
|
||||
- client.pem
|
||||
- cacert.pem
|
||||
roles:
|
||||
- linux-system-roles.network
|
||||
|
|
@ -974,6 +974,51 @@ class NMUtil:
|
|||
else:
|
||||
s_ip6.add_route(rr)
|
||||
|
||||
if connection["802.1x"]:
|
||||
s_8021x = self.connection_ensure_setting(con, NM.Setting8021x)
|
||||
|
||||
s_8021x.set_property(NM.SETTING_802_1X_EAP, [connection["802.1x"]["eap"]])
|
||||
s_8021x.set_property(
|
||||
NM.SETTING_802_1X_IDENTITY, connection["802.1x"]["identity"]
|
||||
)
|
||||
|
||||
s_8021x.set_property(
|
||||
NM.SETTING_802_1X_PRIVATE_KEY,
|
||||
Util.path_to_glib_bytes(connection["802.1x"]["private-key"]),
|
||||
)
|
||||
|
||||
if connection["802.1x"]["private-key-password"]:
|
||||
s_8021x.set_property(
|
||||
NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD,
|
||||
connection["802.1x"]["private-key-password"],
|
||||
)
|
||||
|
||||
if connection["802.1x"]["private-key-password-flags"]:
|
||||
s_8021x.set_secret_flags(
|
||||
NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD,
|
||||
Util.NM().SettingSecretFlags(
|
||||
Util.convert_passwd_flags_nm(
|
||||
connection["802.1x"]["private-key-password-flags"]
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
s_8021x.set_property(
|
||||
NM.SETTING_802_1X_CLIENT_CERT,
|
||||
Util.path_to_glib_bytes(connection["802.1x"]["client-cert"]),
|
||||
)
|
||||
|
||||
if connection["802.1x"]["ca-cert"]:
|
||||
s_8021x.set_property(
|
||||
NM.SETTING_802_1X_CA_CERT,
|
||||
Util.path_to_glib_bytes(connection["802.1x"]["ca-cert"]),
|
||||
)
|
||||
|
||||
s_8021x.set_property(
|
||||
NM.SETTING_802_1X_SYSTEM_CA_CERTS,
|
||||
connection["802.1x"]["system-ca-certs"],
|
||||
)
|
||||
|
||||
try:
|
||||
con.normalize()
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
# vim: fileencoding=utf8
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import posixpath
|
||||
import socket
|
||||
|
||||
# pylint: disable=import-error, no-name-in-module
|
||||
|
|
@ -698,6 +699,59 @@ class ArgValidator_DictMacvlan(ArgValidatorDict):
|
|||
return result
|
||||
|
||||
|
||||
class ArgValidatorPath(ArgValidatorStr):
|
||||
"""
|
||||
Valides that the value is a valid posix absolute path
|
||||
"""
|
||||
|
||||
def __init__(self, name, required=False, default_value=None):
|
||||
ArgValidatorStr.__init__(self, name, required, default_value, None)
|
||||
|
||||
def _validate_impl(self, value, name):
|
||||
ArgValidatorStr._validate_impl(self, value, name)
|
||||
|
||||
if posixpath.isabs(value) is False:
|
||||
raise ValidationError(
|
||||
name, "value '%s' is not a valid posix absolute path" % (value),
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
class ArgValidator_Dict802_1X(ArgValidatorDict):
|
||||
|
||||
VALID_EAP_TYPES = ["tls"]
|
||||
|
||||
VALID_PRIVATE_KEY_FLAGS = ["none", "agent-owned", "not-saved", "not-required"]
|
||||
|
||||
def __init__(self):
|
||||
ArgValidatorDict.__init__(
|
||||
self,
|
||||
name="802.1x",
|
||||
nested=[
|
||||
ArgValidatorStr(
|
||||
"eap",
|
||||
enum_values=ArgValidator_Dict802_1X.VALID_EAP_TYPES,
|
||||
default_value="tls",
|
||||
),
|
||||
ArgValidatorStr("identity", required=True),
|
||||
ArgValidatorPath("private-key", required=True),
|
||||
ArgValidatorStr("private-key-password"),
|
||||
ArgValidatorList(
|
||||
"private-key-password-flags",
|
||||
nested=ArgValidatorStr(
|
||||
"private-key-password-flags[?]",
|
||||
enum_values=ArgValidator_Dict802_1X.VALID_PRIVATE_KEY_FLAGS,
|
||||
),
|
||||
default_value=None,
|
||||
),
|
||||
ArgValidatorPath("client-cert", required=True),
|
||||
ArgValidatorPath("ca-cert"),
|
||||
ArgValidatorBool("system-ca-certs", default_value=False),
|
||||
],
|
||||
default_value=None,
|
||||
)
|
||||
|
||||
|
||||
class ArgValidator_DictConnection(ArgValidatorDict):
|
||||
|
||||
VALID_PERSISTENT_STATES = ["absent", "present"]
|
||||
|
|
@ -759,6 +813,7 @@ class ArgValidator_DictConnection(ArgValidatorDict):
|
|||
ArgValidator_DictInfiniband(),
|
||||
ArgValidator_DictVlan(),
|
||||
ArgValidator_DictMacvlan(),
|
||||
ArgValidator_Dict802_1X(),
|
||||
# deprecated options:
|
||||
ArgValidatorStr(
|
||||
"infiniband_transport_mode",
|
||||
|
|
@ -1208,3 +1263,18 @@ class ArgValidator_ListConnections(ArgValidatorList):
|
|||
"profile references a master '%s' which has 'interface_name' "
|
||||
"missing" % (connection["master"]),
|
||||
)
|
||||
|
||||
# check if 802.1x connection is valid
|
||||
if connection["802.1x"]:
|
||||
if mode == self.VALIDATE_ONE_MODE_INITSCRIPTS:
|
||||
raise ValidationError.from_connection(
|
||||
idx,
|
||||
"802.1x authentication is not supported by initscripts. "
|
||||
"Configure 802.1x in /etc/wpa_supplicant.conf "
|
||||
"if you need to use initscripts.",
|
||||
)
|
||||
|
||||
if connection["type"] != "ethernet":
|
||||
raise ValidationError.from_connection(
|
||||
idx, "802.1x settings only allowed for ethernet interfaces."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,33 @@ class Util:
|
|||
raise MyError("failure calling %s: exit with %s" % (argv, p.returncode))
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def path_to_glib_bytes(path):
|
||||
"""
|
||||
Converts a path to a GLib.Bytes object that can be accepted by NM
|
||||
"""
|
||||
return Util.GLib().Bytes.new(("file://%s\x00" % path).encode("utf-8"))
|
||||
|
||||
@staticmethod
|
||||
def convert_passwd_flags_nm(secret_flags):
|
||||
"""
|
||||
Converts an array of "secret flags" strings
|
||||
to an integer represantion understood by NetworkManager
|
||||
"""
|
||||
|
||||
flag_int = 0
|
||||
|
||||
if "none" in secret_flags:
|
||||
flag_int += 0
|
||||
if "agent-owned" in secret_flags:
|
||||
flag_int += 1
|
||||
if "not-saved" in secret_flags:
|
||||
flag_int += 2
|
||||
if "not-required" in secret_flags:
|
||||
flag_int += 4
|
||||
|
||||
return flag_int
|
||||
|
||||
@classmethod
|
||||
def create_uuid(cls):
|
||||
return str(uuid.uuid4())
|
||||
|
|
|
|||
|
|
@ -32,6 +32,17 @@
|
|||
when:
|
||||
- network_provider == "nm"
|
||||
|
||||
# If any 802.1x connections are used, the wpa_supplicant
|
||||
# service is required to be running
|
||||
- name: Enable and start wpa_supplicant
|
||||
service:
|
||||
name: wpa_supplicant
|
||||
state: started
|
||||
enabled: true
|
||||
when:
|
||||
- network_provider == "nm"
|
||||
- wpa_supplicant_required
|
||||
|
||||
- name: Enable network service
|
||||
service:
|
||||
name: "{{ network_service_name }}"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ IGNORE = [
|
|||
"tests_default_nm.yml",
|
||||
"tests_default_initscripts.yml",
|
||||
"tests_default.yml",
|
||||
"tests_802_1x_nm.yml",
|
||||
]
|
||||
|
||||
OTHER_PLAYBOOK = """
|
||||
|
|
|
|||
32
tests/files/cacert.pem
Normal file
32
tests/files/cacert.pem
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
O/Ut71oKxQ/z0H/Iy1BiBoUzuK0XL079lou4ft0=
|
||||
-----END CERTIFICATE-----
|
||||
31
tests/files/client.key
Normal file
31
tests/files/client.key
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# password=test
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,C4A5E9A189773AB0F3CE3DCC98F208AE
|
||||
|
||||
LPNSExpEERS+/qHJxd8puT+EaZ/dZ20gkU/C2eaNNJerzr4moSXG4ioh5ggz4utQ
|
||||
w57fD5OYqPiloNIawi/Ta5Opo3zU+iMZPVQALLbemXWXmNMxqxNCGdonc4enxMoN
|
||||
auLxpdYPW+infFmf0UPwZjWkrLnK8XFapTGDaNesfgMNSRVSt+DQL3xeKUjcuXfh
|
||||
rYvF26/Ls8NHB0tCU449vCa5ta1fHPT78B0cWgCmhcg/L8/0veBYfwxnyu6l3E6Q
|
||||
RXWcyaJoihhCSg9kCZOqQFKDtz3B9G8/G8P5n5udN2TYUK0ieCktocOip0r/aUfk
|
||||
Rz/NPjej18tuvA9e+uho2DuEj7OV1Rt0Fr6G2NySDYAIjlzM1+GoDdX3R8Rva2eX
|
||||
SJYEjQvvLMAXU9wLEGd2u9jw3h8g2rNPF34Mo/fZsU6f83WceN7wzaDjKBM9TC/U
|
||||
DjeUpJ2LHr3SduRoq5K7PqTG6LlRx4ZC06P8Gwu/cjlHqHuMlLE6wWPHowp9O08S
|
||||
zMzJji6csSzZ5x5U41xiBJd19G0tbfjGBOvxhVLC3hmfqMtRwgeKSZMUz5f0iFvS
|
||||
V4LE/ZNXWv5OybEzMyIiQBRB0G8mq5BkQ3rU9uTMO6Xc6mosQy0jiCsQLYaX2IoT
|
||||
kyU6ZqPgAeBD3g5zCGudcF4qqY3pWRU6cijpivsuyX58YmulhQJsB2rnoImv8ZOR
|
||||
4Uw+fvAx38v/dH/aAGKNdQV/4z+CXpAX4SdqYgBx9wXu6Wva31AVrbDrKnpSlWYF
|
||||
M9gAHgpuhW9OH7du/y7sePU6k37fHtqDX0V5XoyeRxixR+KGb8k3tt0HFA1GExSu
|
||||
XyXcOOfwec7xNQjZBM9jREI0yO1tCbHEeLsLpQnf31cpfSQumBZoiim6Vyk7vCN8
|
||||
YBJ9qiVNrFiVogWl5hUrSS2MLQP1ZQBkedmOeKZpkZ26GW5yY0y27v2mHdhU2Dvd
|
||||
otvLGiVKxSXlu+tqt1WkMvu6hcfrDZDCONW7emGW7xs2vdYdvADVlYs/Eb0WFXb1
|
||||
tLkwg3v7I23LeFRrKX4Fm5/biG4GuR4sj9iPLayrKWhpujIVFJqHTI3YhjIU56Qp
|
||||
uPuClnoFsKrWS9DXaziuuXmLZlXH3e5aOO+M2H3JmXTRCojyjKlIJiJJmHGrfwfe
|
||||
oJkSF+ABs2zrpteXU+Cnfn8V01TrtxPYIBF3CbOMZEvwgjPLX0UNtnss0hXH4rJe
|
||||
9yF/PiKWehUow8q4Gpwt2PnLkUWyL21GwCwXf5Cq3yRAKtyrJTlJsdYV1f3brzfb
|
||||
JkBgKaFJ44Ee7D75PAio8g/BIDpvUdZVXwn3FizjfAU+HhXonPSYb2M34C6I/frk
|
||||
mJPgZ5hbpt1SoCCER48+rQygiLdNQH6OsuhJeEElPFYwNo6i5jZsZ9iE0rmJxGgk
|
||||
m7Mhi491NdK8L6Kh8kM2Dgupsfcstmx4+pI3gmgnsYZApmFoQlfcg4MhbWqxznv+
|
||||
cPm1n2SZMoMLru44vbnjW+ZAggen5zNZOrsVt8UImSBVKfAIrgDUuYIv7uqUiKHI
|
||||
yHmAkZDlqEbpkbUG9m60OeuEIgpN7MT3Kod387ZyOu9uaTZWdD18/N83E4eFecND
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
tests/files/client.key.nocrypt
Normal file
27
tests/files/client.key.nocrypt
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAuQipSk9+0rd/qBMDRiFzV8vDksaueVphejGEgiQhqtUDgjc/
|
||||
ot/o7M8fFVC6wau2ixTnEMHuZXgoBOKATxX805FggEsLLL98OnN7AyTTKOtHVfIm
|
||||
gK3fJ1Y9l95+2nuJWhmaan0vr3YMp6z3lSa+hlhhTYx/mIvTZho/K3+METg8DEfl
|
||||
QUSkhAlrFSEahr2Pu/yETr8c+8vKTDnZDLvcFyyuDtAz+clEQUVndWJQpQpSVfR9
|
||||
4xKuzaj10mUA9Utv4RkbNJ78/KgdTbaGIOVLUnYCJUg8d3/YV7aNCqraHBAZ9aoP
|
||||
S4dl46KXC3qpaEBFfKaF+RcPSVUtc4eCQ74kKwIDAQABAoIBAGoArUN2IVjEaSy3
|
||||
n7OIrFSK1oL6sa+x+JARWDFaU7NTj0wFLL65ee5Yhh0m/6a+IbiyA+IUx+d3m62Y
|
||||
uRsVpJ7r9RXqZ/99v8SYrctSSGpzx41USXyEn4ggnu6nN5MhHMHyUwVYrH3fqkZR
|
||||
EBFxfcrnTO8pY1vYFwayWKgpzOt7ip30JF1E7RH0IWfA2koJ+hZgSumPmF31btBK
|
||||
eqDaQ168u0at6I7nYvRIWVT68D2k+PMb/c/rlOUYSyy+VfCgnShWD+m1hlyaDF1c
|
||||
cbVvOhsul3rFeEqbToGN/6yyDDcyolTvYxMm3vb6jmoExZyRsShv0XyhokSuCN9P
|
||||
v5SeNpkCgYEA7OpIlsZUoTXm2ffCQiZd8gRtKk0O3dzmWTkcNEgj2uUNH6ANNy3W
|
||||
gLojKeF2EyC3appRWLVRYN/m6r/Qj+rztZfW3Jw1UJQV+tLEOBzk3yBnRdh1aRgW
|
||||
8YTH1+HJqlJ/2iKJRKRhseM5AHiTslp7ude6cWQxO52pJ6Rbp1z3fBUCgYEAx/B4
|
||||
LreIDJYDnYSyL/CvVkHEn1hCYX0oBpefzV6ofYDqv0OLe8BWOBsShQ3Crh0FuQTa
|
||||
xV2xc+OzDewlu2OwNm4/X0qjXvoWkEMLBXKEHjPyxnbHLCYaaA/9ENmVIkc8aZWE
|
||||
p7KcCYGlfiHpbdYWAD8KYdv5CsFHFbwhPwrD7z8CgYAEtsSq+1dDvebR/3QGDO1h
|
||||
m2TwqofZMkQDEnfVMnpEKLqSHoUky+ywswNwGeRXjRcZL+jecv0jiFD36skjk/E1
|
||||
c8f6q8ED0W5+hyMQWsLTDboAUcZESQ5rz9CKIxv4H5wbowRIMV0gRP0lXUDTE6nS
|
||||
kNBM4Ul5fjGXcFXChr8F4QKBgGSmAeoKi9tCHTnLVePaNnmmi/Nm+6uV1HNVGqXI
|
||||
k+rx3bpAp1O5o+2Ee1MtdSYvB/V2oyadnrnnEvjcOrZVXZxY7V/r88fY/0jJ5x9r
|
||||
4WRO5FTR8DuiRsLB4bP8xB1IXPoNwYSl3fTPJd8T9S1MizC+i1xt3rVyTHV9igLx
|
||||
SWcDAoGBAMoynJvQUOssWwFTtNQK0ptz95rrTkO2bri+8MJfSh8tessekwPHVe6M
|
||||
SBofFhDiesrHBHczJ61qDnb3GemA0kEbo023mxNo0HPam+OFgX5mrihizBZnRZjh
|
||||
aecVouDd0uwacsB76fwP6Fl5GhkFvOSBKr2IKNJjUMXyvW8/XGZE
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
tests/files/client.pem
Normal file
27
tests/files/client.pem
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqDCCApCgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwVDELMAkGA1UEBhMCWFgx
|
||||
FTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55
|
||||
IEx0ZDEQMA4GA1UEAwwHVGVzdCBDQTAeFw0yMDAyMjgwOTQ0MjlaFw00NzA3MTUw
|
||||
OTQ0MjlaMF0xCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAa
|
||||
BgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQxGTAXBgNVBAMMEFRlc3QgQ2xpZW50
|
||||
IENlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5CKlKT37St3+o
|
||||
EwNGIXNXy8OSxq55WmF6MYSCJCGq1QOCNz+i3+jszx8VULrBq7aLFOcQwe5leCgE
|
||||
4oBPFfzTkWCASwssv3w6c3sDJNMo60dV8iaArd8nVj2X3n7ae4laGZpqfS+vdgyn
|
||||
rPeVJr6GWGFNjH+Yi9NmGj8rf4wRODwMR+VBRKSECWsVIRqGvY+7/IROvxz7y8pM
|
||||
OdkMu9wXLK4O0DP5yURBRWd1YlClClJV9H3jEq7NqPXSZQD1S2/hGRs0nvz8qB1N
|
||||
toYg5UtSdgIlSDx3f9hXto0KqtocEBn1qg9Lh2XjopcLeqloQEV8poX5Fw9JVS1z
|
||||
h4JDviQrAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5T
|
||||
U0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBShQJXhPekXBpAdhKUK
|
||||
vwip1379NzAfBgNVHSMEGDAWgBQ4kXolXxDcc+46nVRmj4rJhx12DDANBgkqhkiG
|
||||
9w0BAQsFAAOCAgEAzY1ifNUYYVvWt0vR+gq37rLG5QZvlt5/pkVDYHgolChZCDmD
|
||||
NWTH5MR/T+L+akFzbuIeOfQzTQMW/8fm9lHf6/e2coDtzLDKkukVCKIGZgrkyF9N
|
||||
wT1xnvqCAERw0WfGFJn7auhIrExqgsrJbAorUMnVZAdrBosDWGMULNquyZMfVvAE
|
||||
VXDDqjQIXe3AMA2yOgMEWoBVQMFl33BTz/NlGaE15wR8OsYRAs8/8nJewCLg4f6a
|
||||
n2wz1/JIZI0ztTCO1cMrmI8i7TYIUlHQMK1QhF0aEFV1yFj+QDEc0iiIZu+i6O45
|
||||
K1TjElXIr4MrEzdI3A5ZIN+VZ7mtzq/2CIZTTir94XLcQ3BvwYJssMWxAPQb6lRA
|
||||
4k+7xifr3V7u7glMxpilIxV5CpZZ4anqRMzFbJa2MOmyAXZxk7SpcD2/MugHfJiL
|
||||
TWfwFcClRogqXx/loEgzXExV1MrYKQBrqMlHB5eZ77M+PFpMhVh7yY5jjWT0giOM
|
||||
MXFFKL8sI3VZdT9VcKZLgKpl4KWDh+cldyJdNNCDA29gtCRO+N+d4CAl6dK6nRrI
|
||||
lL81UTEexmaCL9YjLBs70/HBKCkUDOmtAR7gJ01S4Kogv4gIepCAcGmVItzF+6fw
|
||||
YsbkynxXIHQcODaB2d7FFzP0QJkc6pSMIi7ioO7a+aYx8NpIDYIxxLzF39Q=
|
||||
-----END CERTIFICATE-----
|
||||
8
tests/files/dh.pem
Normal file
8
tests/files/dh.pem
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEAjbYPkANn2XGqDGCzse9wAfM0I5WJpp+Xl+iNJFmaKXBguo0BPYQt
|
||||
hZOpJbKL3aNaFsRxhdAJ8UXzBP6oIzCejcGti+jw+xtVk8ietWEK6e91yi+Ak2g2
|
||||
/Xtt9hoYQkeoe5hkcv35NcJ0xdQwlSvMbY/j8HtKamx/A3zu+YPQAe/3AOe3L+JT
|
||||
iEL5Gw00NPVnyEWKX4fVchAbMUkRsQKeXtsyOyDc4/RccjfLa1toyj8PRommK5UH
|
||||
dkSqi04FTOUIx6aTwt21EehJuggLVDShoQdxGV+FzXmdtelLmerGMtVPBbf8DSkN
|
||||
MKMBEg4d28DzjXPAWUHMD+JGPzAlvf87EwIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
31
tests/files/server.key
Normal file
31
tests/files/server.key
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# password=test
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,ED349A8B098E2D1DB70C30F77EF599AB
|
||||
|
||||
j1rzje2sWFk3B9kD6eE7WrqVDynFEJ3t3kdOv0iUvH5Ybll1C7Qx3EFEdoM4z2OV
|
||||
E6q3nr2DOvpMPox1DvBdIipWOQWJxkZyBHqNn4v4GR4c0uxLswsk7XSBQLUclRsn
|
||||
QBGO6x8pcEA9u/O3PSrTt+pVozWrXWmR2UHNM//9WUsRpWF4Lv0EINzsfwmD7aJQ
|
||||
nRcSfXsCggXP6wnJX5dgo5PlRm6R+bodgzePr0QRlh8TT6wnixZfWalYM5iUKlEF
|
||||
GcE+VejZuBL69byl2AcRt8I5tQ+UZxmzhKPSsYN0NKD8vbcVVnp2sre/rbdTzWz5
|
||||
laF386g1M8QBimDE/V3Bw5b9Bg1ZP3arlpugVXGVNA+HFti8PVdkaMqLgkFIC2Xu
|
||||
OwmNKffAPIItuB8leg5A76oLoIlllRqjWO9M/O+MqAlrJ96xLRiUeGkez4Pp7eFV
|
||||
30YrlOXyzwZKfXoOPIfE5Mbz4CPqR67XuqW8jOryIGOryMB17b0+vdRpDY0wxk8/
|
||||
lGmc5rglDxLFA8dNemAHDednasCuVlrbsQsZRnPkKavXiSu7QCbvm1frAXZfnyRp
|
||||
TpPmE6L4+nEy8PQnK/IxOCqRcy6e1SPezRpajRjB5ooDT8hDmDkG47NdnrB+kOKL
|
||||
5LIpATLSGS9IVk0RW/M8EqJP1kRh2JOCQT3V+gUN0ttz8bjZpivKnp76/ztg0lo0
|
||||
oC2lhuXV5HOYHw1z5jDazsYpQDYoHgYWXnzPJJp6Ecn+nkjZMKQjDV9ZqE1miPrZ
|
||||
E4V0ULNmWaAQHvwc98yR97ui1YHmw5XVMoeDhy3fhB6IOyaGGdEj9o2iQr8kp9GC
|
||||
dxBKK/xMOU6kwDF9Nsfh46veRGTbhAJdGeWqdxscdCupkO8KRtZqzL454+9GnYfe
|
||||
n1f7wxJh7aTLNjF2an5Qa9v7uU6D58+9blxG7ls5qGt4xjBNAXCc8bPpmLqeCW4G
|
||||
Xz8iwxECvwWIQ+SjUcXuP8+/NO58B14kDNP03+1gA7AHIesa2CTvHLCyMPaN2oGK
|
||||
3R4LNxQQDNygEzRj8vHjURU1FNRJ4RjCi7SbqoOsl31Hvef6j0lcW0Sz4UICcCJI
|
||||
p4NPnApoaHewL4exvlJ80qPbFscuVevXBlUC2LdxXS+9E+c0NaLauEeNYCUoaBDi
|
||||
HIpbxRKXmqLc4LAKYVuEcIBFhdXp3UC9niVd7Nrguu0lUJXC78OzpltxWrqX/u4E
|
||||
O2aCNK0Yg9U+rxm6wyccqEyptIS2GRCIpUGD/LVF3mOC16NB/JeYGrOWvDptdCeg
|
||||
9pJrakJjE1Fm3pg4Xc74bT6IDj0EKwKSvZhtlcsM9JaXWChe/ZrDPPI/NP6MuyW4
|
||||
jcqpa9HPBBSyaxKsEPXFJhdhrz8VfsU2e5VvcALaJaAOpHwZgaNUpvpsY4LPW9mi
|
||||
lHsecEBiq6re0r7TAgBE1AnlaI4ho0fKSgSub3NWUZlEaBK3X2n/Li6op6LIsvM5
|
||||
iySYaAluQy4dANww0KhQHMIh0jbuZGzmG2Hxk/poorYRf60YJlbTnHVD/FKUdFX+
|
||||
rUow0iy8Ez1uF272u5orYW2tBbkhSaieKOT8f4HFCxUsgITbd8Lf/XJ6l6Qns6SK
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
tests/files/server.pem
Normal file
27
tests/files/server.pem
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqDCCApCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwVDELMAkGA1UEBhMCWFgx
|
||||
FTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55
|
||||
IEx0ZDEQMA4GA1UEAwwHVGVzdCBDQTAeFw0yMDAyMjgwOTA2MTlaFw00NzA3MTUw
|
||||
OTA2MTlaMF0xCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAa
|
||||
BgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQxGTAXBgNVBAMMEFRlc3QgU2VydmVy
|
||||
IENlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFwLjgCZ0pAEPB
|
||||
HrtoxM+qY27od+Np1mqwPbFmPlcxV2fiRquqxVghsow6r5JHOCblpn+TNAgKlckx
|
||||
d+PXpwgPoELE15x8lU5+8/IjSQJRsx/VhmJEbYWYHZWwbwBUMZaafhrtKZfJoIDR
|
||||
pzx2SKmeUIXad10uFwFqT8uz6GNFg3tVIsu/E7wpPjaK+G4/1iAZjUrli1p73Qfg
|
||||
cGIrFueTA5TGL3ChsRFJdIuBvh765fxZGurEghiYcX4bO/mSKVEWs/AoGajeJ1U+
|
||||
uqOxyFl7Sjyb+ds2jdLNYYj191efT4qBmhB0bdmLFfq46GsKoneImaceSnhpcovl
|
||||
jsmZf8UVAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5T
|
||||
U0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTHtNcLFSKihvvmv/WQ
|
||||
zKkJjL0yPTAfBgNVHSMEGDAWgBQ4kXolXxDcc+46nVRmj4rJhx12DDANBgkqhkiG
|
||||
9w0BAQsFAAOCAgEALDrMv9TBWjVMeBUaRiaF+CDVD+Ng1Frzp37tSLbBmfcViaPl
|
||||
2vQ23wDTc0SU+bamfyrIF0IRDDNM6cUkuC306+18AtXcz1taPFu6mWhtz+j4Hncm
|
||||
EpMSUxvmTvr9dSUuEdX74v7tA4YqThzolEbsedAr8oe6RBjntAKugG9035z/mWuO
|
||||
WNw8P3QI6eSX/APzFON/9dt9fkKU2piKgDQYvNEtCPqp1Tr2MkdRzfvyL/ZGR5yn
|
||||
kuSRZLSFJyBHnnjCjrK40nt0ooVFXTpqDb8gEFn3DOLXHWLy6tWAQi6fKBQWai7v
|
||||
8Mz7OyQHEwEsdM3bLWVJwe4tzJA2Ct22HsHWixuEEtQFwnuGm/tEOJ3HwVPjn5QP
|
||||
2ut8yH5Ij45XeBTxkMiKie/Eb43ob8o30jCUtGuM48azyZ+byaIqVYZ/DX8NQAdC
|
||||
EGRA1nWHmr9nFvcpa98kjiKcQtb7Nb/Ewq5ys/mYAwAs3yD9FNt+ujb1/y9PLN5Q
|
||||
+NkcFrPuCmIj5c3jOi0AwPD+WuTHBwJ3D7+2gUByVYf6GravI6N6uXEjOD2/Wcl0
|
||||
TtjlhiWvMK9bXu2F4FBLc+GXrawiG4aTNmi278bTSF6qIxrN5+A5JRU7eUtbCnpY
|
||||
piA3Y/2Pu8YoM3coGWqtVfFddJr1raQ5LHjxIfDUd0kKPbfpjlaaa3aJQdg=
|
||||
-----END CERTIFICATE-----
|
||||
1
tests/playbooks/files
Symbolic link
1
tests/playbooks/files
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../files
|
||||
106
tests/playbooks/tests_802_1x.yml
Normal file
106
tests/playbooks/tests_802_1x.yml
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
---
|
||||
- hosts: all
|
||||
vars:
|
||||
interface: 802-1x-test
|
||||
tasks:
|
||||
- name: "INIT: 802.1x tests"
|
||||
debug:
|
||||
msg: "##################################################"
|
||||
- include_tasks: tasks/setup-802_1x_server.yml
|
||||
- name: Copy client certs
|
||||
copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/pki/tls/{{ item }}"
|
||||
mode: 0644
|
||||
with_items:
|
||||
- client.key
|
||||
- client.key.nocrypt
|
||||
- client.pem
|
||||
- cacert.pem
|
||||
- block:
|
||||
- name: "TEST: 802.1x profile with private key password and ca cert"
|
||||
debug:
|
||||
msg: "##################################################"
|
||||
- import_role:
|
||||
name: linux-system-roles.network
|
||||
vars:
|
||||
network_connections:
|
||||
- name: "{{ interface }}"
|
||||
interface_name: veth2
|
||||
state: up
|
||||
type: ethernet
|
||||
ip:
|
||||
address:
|
||||
- 203.0.113.2/24
|
||||
dhcp4: "no"
|
||||
auto6: "no"
|
||||
802.1x:
|
||||
identity: myhost
|
||||
eap: tls
|
||||
private-key: /etc/pki/tls/client.key
|
||||
private-key-password: test
|
||||
private-key-password-flags:
|
||||
- none
|
||||
client-cert: /etc/pki/tls/client.pem
|
||||
ca-cert: /etc/pki/tls/cacert.pem
|
||||
- name: "TEST: I can ping the EAP server"
|
||||
shell: ping -c1 203.0.113.1
|
||||
- import_role:
|
||||
name: linux-system-roles.network
|
||||
vars:
|
||||
network_connections:
|
||||
- name: "{{ interface }}"
|
||||
persistent_state: absent
|
||||
state: absent
|
||||
- name: >-
|
||||
TEST: 802.1x profile with unencrypted private key and
|
||||
system ca certs
|
||||
debug:
|
||||
msg: "##################################################"
|
||||
- name: Copy cacert to system truststore
|
||||
copy:
|
||||
src: cacert.pem
|
||||
dest: /etc/pki/ca-trust/source/anchors/cacert.pem
|
||||
mode: 0644
|
||||
- name: Update ca trust
|
||||
shell: update-ca-trust
|
||||
- import_role:
|
||||
name: linux-system-roles.network
|
||||
vars:
|
||||
network_connections:
|
||||
- name: "{{ interface }}"
|
||||
interface_name: veth2
|
||||
state: up
|
||||
type: ethernet
|
||||
ip:
|
||||
address:
|
||||
- 203.0.113.2/24
|
||||
dhcp4: "no"
|
||||
auto6: "no"
|
||||
802.1x:
|
||||
identity: myhost
|
||||
eap: tls
|
||||
private-key: /etc/pki/tls/client.key.nocrypt
|
||||
client-cert: /etc/pki/tls/client.pem
|
||||
private-key-password-flags:
|
||||
- not-required
|
||||
system-ca-certs: True
|
||||
- name: "TEST: I can ping the EAP server"
|
||||
shell: ping -c1 203.0.113.1
|
||||
always:
|
||||
- block:
|
||||
- import_role:
|
||||
name: linux-system-roles.network
|
||||
vars:
|
||||
network_connections:
|
||||
- name: "{{ interface }}"
|
||||
persistent_state: absent
|
||||
state: absent
|
||||
- name: br1
|
||||
persistent_state: absent
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
- include_tasks: tasks/cleanup-802_1x_server.yml
|
||||
tags:
|
||||
- "tests::cleanup"
|
||||
11
tests/tasks/cleanup-802_1x_server.yml
Normal file
11
tests/tasks/cleanup-802_1x_server.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
---
|
||||
- name: Remove test interfaces
|
||||
shell: |
|
||||
ip netns delete ns1
|
||||
ip link delete veth1-br
|
||||
ip link delete veth2-br
|
||||
ip link delete br1
|
||||
|
||||
- name: Kill hostapd process
|
||||
shell: pkill hostapd
|
||||
80
tests/tasks/setup-802_1x_server.yml
Normal file
80
tests/tasks/setup-802_1x_server.yml
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
---
|
||||
- name: Install EPEL on enterprise Linux for hostapd
|
||||
# yamllint disable-line rule:line-length
|
||||
command: yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm
|
||||
args:
|
||||
warn: false
|
||||
creates: /etc/yum.repos.d/epel.repo
|
||||
when:
|
||||
- ansible_distribution in ['RedHat', 'CentOS']
|
||||
|
||||
- name: Install hostapd
|
||||
package:
|
||||
name: hostapd
|
||||
state: present
|
||||
|
||||
- name: Copy server certificates
|
||||
copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/pki/tls/{{ item }}"
|
||||
with_items:
|
||||
- server.key
|
||||
- dh.pem
|
||||
- server.pem
|
||||
- cacert.pem
|
||||
|
||||
- name: Create test interfaces
|
||||
shell: |
|
||||
ip link add veth1 type veth peer name veth1-br
|
||||
ip link add veth2 type veth peer name veth2-br
|
||||
|
||||
ip link add br1 type bridge
|
||||
ip link set br1 up
|
||||
|
||||
ip netns add ns1
|
||||
|
||||
ip link set veth1 netns ns1
|
||||
|
||||
ip netns exec ns1 ip addr add 203.0.113.1/24 dev veth1
|
||||
|
||||
ip link set veth1-br up
|
||||
ip link set veth2-br up
|
||||
|
||||
ip link set veth1-br master br1
|
||||
ip link set veth2-br master br1
|
||||
|
||||
ip netns exec ns1 ip link set veth1 up
|
||||
ip link set veth2 up
|
||||
|
||||
# Enable forwarding of EAP 802.1x messages through software bridge "br1".
|
||||
echo 8 > /sys/class/net/br1/bridge/group_fwd_mask
|
||||
|
||||
- name: Create hostapd config
|
||||
copy:
|
||||
content: |
|
||||
interface=veth1
|
||||
driver=wired
|
||||
debug=2
|
||||
ieee8021x=1
|
||||
eap_reauth_period=3600
|
||||
eap_server=1
|
||||
use_pae_group_addr=1
|
||||
eap_user_file=/etc/hostapd/hostapd.eap_user
|
||||
ca_cert=/etc/pki/tls/cacert.pem
|
||||
dh_file=/etc/pki/tls/dh.pem
|
||||
server_cert=/etc/pki/tls/server.pem
|
||||
private_key=/etc/pki/tls/server.key
|
||||
private_key_passwd=test
|
||||
logger_syslog=-1
|
||||
logger_syslog_level=0
|
||||
dest: /etc/hostapd/wired.conf
|
||||
|
||||
- name: Create eap_user_file config
|
||||
copy:
|
||||
content: |
|
||||
* TLS
|
||||
dest: /etc/hostapd/hostapd.eap_user
|
||||
|
||||
- name: Run hostapd in namespace
|
||||
shell: ip netns exec ns1 hostapd -B /etc/hostapd/wired.conf && sleep 5
|
||||
15
tests/tests_802_1x_nm.yml
Normal file
15
tests/tests_802_1x_nm.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
# set network provider and gather facts
|
||||
- hosts: all
|
||||
tasks:
|
||||
- name: Set network provider to 'nm'
|
||||
set_fact:
|
||||
network_provider: nm
|
||||
|
||||
# workaround for: https://github.com/ansible/ansible/issues/27973
|
||||
# There is no way in Ansible to abort a playbook hosts with specific OS
|
||||
# releases Therefore we include the playbook with the tests only if the hosts
|
||||
# would support it.
|
||||
# The test requires NetworkManager, therefore it cannot run on RHEL/CentOS 6
|
||||
- import_playbook: playbooks/tests_802_1x.yml
|
||||
when: ansible_distribution_major_version != '6'
|
||||
|
|
@ -66,6 +66,7 @@ def pprint(msg, obj):
|
|||
|
||||
ARGS_CONNECTIONS = network_lsr.argument_validator.ArgValidator_ListConnections()
|
||||
VALIDATE_ONE_MODE_INITSCRIPTS = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
VALIDATE_ONE_MODE_NM = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_NM
|
||||
|
||||
ETHTOOL_FEATURES_DEFAULTS = {
|
||||
"esp-hw-offload": None,
|
||||
|
|
@ -153,6 +154,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "5",
|
||||
"parent": None,
|
||||
|
|
@ -197,7 +199,8 @@ class TestValidator(unittest.TestCase):
|
|||
if "type" in connection:
|
||||
connection["nm.exists"] = False
|
||||
connection["nm.uuid"] = n.Util.create_uuid()
|
||||
mode = VALIDATE_ONE_MODE_INITSCRIPTS
|
||||
|
||||
mode = VALIDATE_ONE_MODE_NM
|
||||
for idx, connection in enumerate(connections):
|
||||
try:
|
||||
ARGS_CONNECTIONS.validate_connection_one(mode, connections, idx)
|
||||
|
|
@ -248,7 +251,7 @@ class TestValidator(unittest.TestCase):
|
|||
continue
|
||||
if "type" not in connection:
|
||||
continue
|
||||
if connection["type"] in ["macvlan"]:
|
||||
if connection["type"] in ["macvlan"] or connection["802.1x"]:
|
||||
# initscripts do not support this type. Skip the test.
|
||||
continue
|
||||
content_current = kwargs.get("initscripts_content_current", None)
|
||||
|
|
@ -394,6 +397,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "5",
|
||||
"parent": None,
|
||||
|
|
@ -444,6 +448,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "5",
|
||||
"parent": None,
|
||||
|
|
@ -488,6 +493,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "5",
|
||||
"parent": None,
|
||||
|
|
@ -575,6 +581,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": "52:54:00:44:9f:ba",
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": 1450,
|
||||
"name": "prod1",
|
||||
"parent": None,
|
||||
|
|
@ -636,6 +643,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "prod1",
|
||||
"parent": None,
|
||||
|
|
@ -699,6 +707,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": "52:54:00:44:9f:ba",
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": 1450,
|
||||
"name": "prod1",
|
||||
"parent": None,
|
||||
|
|
@ -754,6 +763,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "prod.100",
|
||||
"parent": "prod1",
|
||||
|
|
@ -836,6 +846,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": "52:54:00:44:9f:ba",
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": 1450,
|
||||
"name": "prod1",
|
||||
"parent": None,
|
||||
|
|
@ -891,6 +902,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "prod.100",
|
||||
"parent": "prod1",
|
||||
|
|
@ -968,6 +980,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": "33:24:10:24:2f:b9",
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": 1450,
|
||||
"name": "eth0-parent",
|
||||
"parent": None,
|
||||
|
|
@ -1018,6 +1031,7 @@ class TestValidator(unittest.TestCase):
|
|||
"mac": None,
|
||||
"macvlan": {"mode": "bridge", "promiscuous": True, "tap": False},
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "veth0.0",
|
||||
"parent": "eth0-parent",
|
||||
|
|
@ -1068,6 +1082,7 @@ class TestValidator(unittest.TestCase):
|
|||
"mac": None,
|
||||
"macvlan": {"mode": "passthru", "promiscuous": False, "tap": True},
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "veth0.1",
|
||||
"parent": "eth0-parent",
|
||||
|
|
@ -1153,6 +1168,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "prod2",
|
||||
"parent": None,
|
||||
|
|
@ -1189,6 +1205,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": "prod2",
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "prod2-slave1",
|
||||
"parent": None,
|
||||
|
|
@ -1249,6 +1266,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "bond1",
|
||||
"parent": None,
|
||||
|
|
@ -1294,6 +1312,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "bond1",
|
||||
"parent": None,
|
||||
|
|
@ -1349,6 +1368,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": "aa:bb:cc:dd:ee:ff",
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "5",
|
||||
"parent": None,
|
||||
|
|
@ -1392,6 +1412,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "5",
|
||||
"parent": None,
|
||||
|
|
@ -1463,6 +1484,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "6643-master",
|
||||
"parent": None,
|
||||
|
|
@ -1499,6 +1521,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": "6643-master",
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "6643",
|
||||
"parent": None,
|
||||
|
|
@ -1551,6 +1574,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "infiniband.1",
|
||||
"parent": None,
|
||||
|
|
@ -1621,6 +1645,7 @@ class TestValidator(unittest.TestCase):
|
|||
"mac": "11:22:33:44:55:66:77:88:99:00:"
|
||||
"11:22:33:44:55:66:77:88:99:00",
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "infiniband.2",
|
||||
"parent": None,
|
||||
|
|
@ -1711,6 +1736,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "555",
|
||||
"parent": None,
|
||||
|
|
@ -1809,6 +1835,7 @@ class TestValidator(unittest.TestCase):
|
|||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": None,
|
||||
"mtu": None,
|
||||
"name": "e556",
|
||||
"parent": None,
|
||||
|
|
@ -1887,6 +1914,255 @@ class TestValidator(unittest.TestCase):
|
|||
],
|
||||
)
|
||||
|
||||
def test_802_1x_1(self):
|
||||
"""
|
||||
Test private key with password
|
||||
"""
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
"actions": ["present", "up"],
|
||||
"autoconnect": True,
|
||||
"check_iface_exists": True,
|
||||
"ethernet": ETHERNET_DEFAULTS,
|
||||
"ethtool": ETHTOOL_DEFAULTS,
|
||||
"force_state_change": None,
|
||||
"ignore_errors": None,
|
||||
"interface_name": "802.1x-1",
|
||||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"dhcp4": True,
|
||||
"address": [],
|
||||
"route_append_only": False,
|
||||
"rule_append_only": False,
|
||||
"route": [],
|
||||
"dns": [],
|
||||
"dns_search": [],
|
||||
"route_metric6": None,
|
||||
"dhcp4_send_hostname": None,
|
||||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"private-key-password": "p@55w0rD",
|
||||
"private-key-password-flags": None,
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"ca-cert": "/etc/pki/tls/cacert.pem",
|
||||
"system-ca-certs": False,
|
||||
},
|
||||
"mtu": None,
|
||||
"name": "802.1x-1",
|
||||
"parent": None,
|
||||
"persistent_state": "present",
|
||||
"slave_type": None,
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"wait": None,
|
||||
"zone": None,
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "802.1x-1",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"private-key-password": "p@55w0rD",
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"ca-cert": "/etc/pki/tls/cacert.pem",
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
def test_802_1x_2(self):
|
||||
"""
|
||||
Test private key without password and system-ca-certs
|
||||
"""
|
||||
self.maxDiff = None
|
||||
self.do_connections_validate(
|
||||
[
|
||||
{
|
||||
"actions": ["present", "up"],
|
||||
"autoconnect": True,
|
||||
"check_iface_exists": True,
|
||||
"ethernet": ETHERNET_DEFAULTS,
|
||||
"ethtool": ETHTOOL_DEFAULTS,
|
||||
"force_state_change": None,
|
||||
"ignore_errors": None,
|
||||
"interface_name": "802.1x-2",
|
||||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"dhcp4": True,
|
||||
"address": [],
|
||||
"route_append_only": False,
|
||||
"rule_append_only": False,
|
||||
"route": [],
|
||||
"dns": [],
|
||||
"dns_search": [],
|
||||
"route_metric6": None,
|
||||
"dhcp4_send_hostname": None,
|
||||
},
|
||||
"mac": None,
|
||||
"master": None,
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"private-key-password": None,
|
||||
"private-key-password-flags": ["not-required"],
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"ca-cert": None,
|
||||
"system-ca-certs": True,
|
||||
},
|
||||
"mtu": None,
|
||||
"name": "802.1x-2",
|
||||
"parent": None,
|
||||
"persistent_state": "present",
|
||||
"slave_type": None,
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"wait": None,
|
||||
"zone": None,
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "802.1x-2",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"private-key-password-flags": ["not-required"],
|
||||
"system-ca-certs": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
def test_invalid_cert_path(self):
|
||||
"""
|
||||
should fail if a relative path is used for 802.1x certs/keys
|
||||
"""
|
||||
self.maxDiff = None
|
||||
self.do_connections_check_invalid(
|
||||
[
|
||||
{
|
||||
"name": "802.1x-bad",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "client.key",
|
||||
"client-cert": "client.pem",
|
||||
"private-key-password-flags": ["not-required"],
|
||||
"system-ca-certs": True,
|
||||
},
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
def test_invalid_password_flag(self):
|
||||
"""
|
||||
should fail if an invalid private key password flag is set
|
||||
"""
|
||||
self.maxDiff = None
|
||||
self.do_connections_check_invalid(
|
||||
[
|
||||
{
|
||||
"name": "802.1x-bad",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"private-key-password-flags": ["bad-flag"],
|
||||
"system-ca-certs": True,
|
||||
},
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
def test_802_1x_initscripts(self):
|
||||
"""
|
||||
should fail to create 802.1x connection with initscripts
|
||||
"""
|
||||
input_connections = [
|
||||
{
|
||||
"name": "802.1x-is",
|
||||
"state": "up",
|
||||
"type": "ethernet",
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"private-key-password-flags": ["not-required"],
|
||||
"system-ca-certs": True,
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
connections = ARGS_CONNECTIONS.validate(input_connections)
|
||||
|
||||
self.assertRaises(
|
||||
n.ValidationError,
|
||||
ARGS_CONNECTIONS.validate_connection_one,
|
||||
VALIDATE_ONE_MODE_INITSCRIPTS,
|
||||
connections,
|
||||
0,
|
||||
)
|
||||
|
||||
def test_802_1x_non_ethernet(self):
|
||||
"""
|
||||
should fail if a non-ethernet interface has 802.1x settings defined
|
||||
"""
|
||||
|
||||
input_connections = [
|
||||
{
|
||||
"name": "802.1x-bond",
|
||||
"state": "up",
|
||||
"type": "bond",
|
||||
"802.1x": {
|
||||
"identity": "myhost",
|
||||
"eap": "tls",
|
||||
"private-key": "/etc/pki/tls/client.key",
|
||||
"client-cert": "/etc/pki/tls/client.pem",
|
||||
"private-key-password-flags": ["not-required"],
|
||||
"system-ca-certs": True,
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
connections = ARGS_CONNECTIONS.validate(input_connections)
|
||||
|
||||
self.assertRaises(
|
||||
n.ValidationError,
|
||||
ARGS_CONNECTIONS.validate_connection_one,
|
||||
VALIDATE_ONE_MODE_NM,
|
||||
connections,
|
||||
0,
|
||||
)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
self.maxDiff = None
|
||||
self.do_connections_check_invalid(
|
||||
|
|
@ -2216,6 +2492,11 @@ class TestNM(unittest.TestCase):
|
|||
connections = nmutil.connection_list()
|
||||
self.assertIsNotNone(connections)
|
||||
|
||||
def test_path_to_glib_bytes(self):
|
||||
result = Util.path_to_glib_bytes("/my/test/path")
|
||||
self.assertIsInstance(result, Util.GLib().Bytes)
|
||||
self.assertEqual(result.get_data(), b"file:///my/test/path\x00")
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
def test_check_output(self):
|
||||
|
|
@ -2223,6 +2504,23 @@ class TestUtils(unittest.TestCase):
|
|||
self.assertEqual(res, "test\n")
|
||||
self.assertRaises(n.MyError, Util.check_output, ["false"])
|
||||
|
||||
def test_convert_passwd_flags_nm(self):
|
||||
test_cases = [
|
||||
([], 0),
|
||||
(["none"], 0),
|
||||
(["agent-owned"], 1),
|
||||
(["not-saved"], 2),
|
||||
(["agent-owned", "not-saved"], 3),
|
||||
(["not-required"], 4,),
|
||||
(["agent-owned", "not-required"], 5),
|
||||
(["not-saved", "not-required"], 6),
|
||||
(["agent-owned", "not-saved", "not-required"], 7),
|
||||
]
|
||||
|
||||
for test_case in test_cases:
|
||||
result = Util.convert_passwd_flags_nm(test_case[0])
|
||||
self.assertEqual(result, test_case[1])
|
||||
|
||||
|
||||
class TestSysUtils(unittest.TestCase):
|
||||
def test_link_read_permaddress(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue