mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Use netifaces module instead of 'ip' command
Netifaces allows to get addresses from local interfaces of the host in safer way than parsing output of the ip command. https://fedorahosted.org/freeipa/ticket/5591 Reviewed-By: David Kupka <dkupka@redhat.com>
This commit is contained in:
@@ -33,6 +33,7 @@ try:
|
|||||||
from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
|
from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
|
||||||
import dns
|
import dns
|
||||||
import gssapi
|
import gssapi
|
||||||
|
import netifaces
|
||||||
|
|
||||||
import nss.nss as nss
|
import nss.nss as nss
|
||||||
import SSSDConfig
|
import SSSDConfig
|
||||||
@@ -1526,39 +1527,31 @@ def unconfigure_nisdomain():
|
|||||||
|
|
||||||
|
|
||||||
def get_iface_from_ip(ip_addr):
|
def get_iface_from_ip(ip_addr):
|
||||||
result = ipautil.run([paths.IP, '-oneline', 'address', 'show'],
|
for interface in netifaces.interfaces():
|
||||||
capture_output=True)
|
if_addrs = netifaces.ifaddresses(interface)
|
||||||
for line in result.output.split('\n'):
|
for family in [netifaces.AF_INET, netifaces.AF_INET6]:
|
||||||
fields = line.split()
|
for ip in if_addrs.get(family, []):
|
||||||
if len(fields) < 6:
|
if ip['addr'] == ip_addr:
|
||||||
continue
|
return interface
|
||||||
if fields[2] not in ['inet', 'inet6']:
|
|
||||||
continue
|
|
||||||
(ip, mask) = fields[3].rsplit('/', 1)
|
|
||||||
if ip == ip_addr:
|
|
||||||
return fields[1]
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("IP %s not assigned to any interface." % ip_addr)
|
raise RuntimeError("IP %s not assigned to any interface." % ip_addr)
|
||||||
|
|
||||||
|
|
||||||
def get_local_ipaddresses(iface=None):
|
def get_local_ipaddresses(iface=None):
|
||||||
args = [paths.IP, '-oneline', 'address', 'show']
|
|
||||||
if iface:
|
if iface:
|
||||||
args += ['dev', iface]
|
interfaces = [iface]
|
||||||
result = ipautil.run(args, capture_output=True)
|
else:
|
||||||
lines = result.output.split('\n')
|
interfaces = netifaces.interfaces()
|
||||||
|
|
||||||
ips = []
|
ips = []
|
||||||
for line in lines:
|
for interface in interfaces:
|
||||||
fields = line.split()
|
if_addrs = netifaces.ifaddresses(interface)
|
||||||
if len(fields) < 6:
|
for family in [netifaces.AF_INET, netifaces.AF_INET6]:
|
||||||
continue
|
for ip in if_addrs.get(family, []):
|
||||||
if fields[2] not in ['inet', 'inet6']:
|
try:
|
||||||
continue
|
ips.append(ipautil.CheckedIPAddress(ip['addr']))
|
||||||
(ip, mask) = fields[3].rsplit('/', 1)
|
except ValueError:
|
||||||
try:
|
continue
|
||||||
ips.append(ipautil.CheckedIPAddress(ip))
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
return ips
|
return ips
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ BuildRequires: python-jwcrypto
|
|||||||
BuildRequires: custodia
|
BuildRequires: custodia
|
||||||
BuildRequires: libini_config-devel >= 1.2.0
|
BuildRequires: libini_config-devel >= 1.2.0
|
||||||
BuildRequires: dbus-python
|
BuildRequires: dbus-python
|
||||||
|
BuildRequires: python-netifaces >= 0.10.4
|
||||||
|
|
||||||
# Build dependencies for unit tests
|
# Build dependencies for unit tests
|
||||||
BuildRequires: libcmocka-devel
|
BuildRequires: libcmocka-devel
|
||||||
@@ -478,7 +479,6 @@ Provides: python2-ipaplatform = %{version}-%{release}
|
|||||||
Requires: %{name}-common = %{version}-%{release}
|
Requires: %{name}-common = %{version}-%{release}
|
||||||
Requires: python-gssapi >= 1.1.2
|
Requires: python-gssapi >= 1.1.2
|
||||||
Requires: gnupg
|
Requires: gnupg
|
||||||
Requires: iproute
|
|
||||||
Requires: keyutils
|
Requires: keyutils
|
||||||
Requires: pyOpenSSL
|
Requires: pyOpenSSL
|
||||||
Requires: python-nss >= 0.16
|
Requires: python-nss >= 0.16
|
||||||
@@ -500,6 +500,7 @@ Requires: python-ldap >= 2.4.15
|
|||||||
Requires: python-requests
|
Requires: python-requests
|
||||||
Requires: python-custodia
|
Requires: python-custodia
|
||||||
Requires: python-dns >= 1.11.1
|
Requires: python-dns >= 1.11.1
|
||||||
|
Requires: python-netifaces >= 0.10.4
|
||||||
|
|
||||||
Conflicts: %{alt_name}-python < %{version}
|
Conflicts: %{alt_name}-python < %{version}
|
||||||
|
|
||||||
@@ -526,7 +527,6 @@ Provides: python3-ipaplatform = %{version}-%{release}
|
|||||||
Requires: %{name}-common = %{version}-%{release}
|
Requires: %{name}-common = %{version}-%{release}
|
||||||
Requires: python3-gssapi >= 1.1.2
|
Requires: python3-gssapi >= 1.1.2
|
||||||
Requires: gnupg
|
Requires: gnupg
|
||||||
Requires: iproute
|
|
||||||
Requires: keyutils
|
Requires: keyutils
|
||||||
Requires: python3-pyOpenSSL
|
Requires: python3-pyOpenSSL
|
||||||
Requires: python3-nss >= 0.16
|
Requires: python3-nss >= 0.16
|
||||||
@@ -548,6 +548,7 @@ Requires: python3-pyldap >= 2.4.15
|
|||||||
Requires: python3-custodia
|
Requires: python3-custodia
|
||||||
Requires: python3-requests
|
Requires: python3-requests
|
||||||
Requires: python3-dns >= 1.11.1
|
Requires: python3-dns >= 1.11.1
|
||||||
|
Requires: python3-netifaces >= 0.10.4
|
||||||
|
|
||||||
%description -n python3-ipalib
|
%description -n python3-ipalib
|
||||||
IPA is an integrated solution to provide centrally managed Identity (users,
|
IPA is an integrated solution to provide centrally managed Identity (users,
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ class BasePathNamespace(object):
|
|||||||
CACERT_P12 = "/root/cacert.p12"
|
CACERT_P12 = "/root/cacert.p12"
|
||||||
ROOT_IPA_CSR = "/root/ipa.csr"
|
ROOT_IPA_CSR = "/root/ipa.csr"
|
||||||
NAMED_PID = "/run/named/named.pid"
|
NAMED_PID = "/run/named/named.pid"
|
||||||
IP = "/sbin/ip"
|
|
||||||
NOLOGIN = "/sbin/nologin"
|
NOLOGIN = "/sbin/nologin"
|
||||||
SBIN_REBOOT = "/sbin/reboot"
|
SBIN_REBOOT = "/sbin/reboot"
|
||||||
SBIN_RESTORECON = "/sbin/restorecon"
|
SBIN_RESTORECON = "/sbin/restorecon"
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import socket
|
|||||||
import re
|
import re
|
||||||
import datetime
|
import datetime
|
||||||
import netaddr
|
import netaddr
|
||||||
|
import netifaces
|
||||||
import time
|
import time
|
||||||
import gssapi
|
import gssapi
|
||||||
import pwd
|
import pwd
|
||||||
@@ -151,24 +152,24 @@ class CheckedIPAddress(netaddr.IPAddress):
|
|||||||
|
|
||||||
if match_local:
|
if match_local:
|
||||||
if addr.version == 4:
|
if addr.version == 4:
|
||||||
family = 'inet'
|
family = netifaces.AF_INET
|
||||||
elif addr.version == 6:
|
elif addr.version == 6:
|
||||||
family = 'inet6'
|
family = netifaces.AF_INET6
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
"Unsupported address family ({})".format(addr.version)
|
||||||
|
)
|
||||||
|
|
||||||
result = run(
|
for interface in netifaces.interfaces():
|
||||||
[paths.IP, '-family', family, '-oneline', 'address', 'show'],
|
for ifdata in netifaces.ifaddresses(interface).get(family, []):
|
||||||
capture_output=True)
|
ifnet = netaddr.IPNetwork('{addr}/{netmask}'.format(
|
||||||
lines = result.output.split('\n')
|
addr=ifdata['addr'],
|
||||||
for line in lines:
|
netmask=ifdata['netmask']
|
||||||
fields = line.split()
|
))
|
||||||
if len(fields) < 4:
|
if ifnet == net or (net is None and ifnet.ip == addr):
|
||||||
continue
|
net = ifnet
|
||||||
|
iface = interface
|
||||||
ifnet = netaddr.IPNetwork(fields[3])
|
break
|
||||||
if ifnet == net or (net is None and ifnet.ip == addr):
|
|
||||||
net = ifnet
|
|
||||||
iface = fields[1]
|
|
||||||
break
|
|
||||||
|
|
||||||
if iface is None:
|
if iface is None:
|
||||||
raise ValueError('No network interface matches the provided IP address and netmask')
|
raise ValueError('No network interface matches the provided IP address and netmask')
|
||||||
|
|||||||
Reference in New Issue
Block a user