pywbem / pywbemtools

A set of tools using pywbem to communicate with WBEM servers
http://pywbemtools.readthedocs.io/en/stable/
Apache License 2.0
12 stars 1 forks source link

Send indications fails from Docker container #1296

Closed KSchopmeyer closed 1 year ago

KSchopmeyer commented 1 year ago

We cannot send indications from a docker container WBEM server to a docker host pywbemlistener because the the docker network (on linux with docker bridge network this is docker0) is used for the docker/host communication and that is a different network than the standard network interface for the host system while we define the pywbemlistener host as the localhost address.pywbemlistener. Generally the response returned to the indication sender is:

 ./send_indication.sh "http://172.17.0.1" -p 8000 -d 4
all http://172.17.0.1
fullurl=http://172.17.0.1:8000 key_opts=
Request payload:
<?xml version="1.0" encoding="utf-8" ?>
    <CIM CIMVERSION="2.0" DTDVERSION="2.4">
      <MESSAGE ID="42" PROTOCOLVERSION="1.4">
        <SIMPLEEXPREQ>
          <EXPMETHODCALL NAME="ExportIndication">
            <EXPPARAMVALUE NAME="NewIndication">
              <INSTANCE CLASSNAME="CIM_AlertIndication">
                <PROPERTY NAME="Severity" TYPE="string">
                  <VALUE>high</VALUE>
                </PROPERTY>
                <PROPERTY NAME="Sequence_Number" TYPE="string">
                  <VALUE>1</VALUE>
                </PROPERTY>
                <PROPERTY NAME="DELTA_TIME" TYPE="string">
                  <VALUE>0</VALUE>
                </PROPERTY>
              </INSTANCE>
            </EXPPARAMVALUE>
          </EXPMETHODCALL>
        </SIMPLEEXPREQ>
      </MESSAGE>
    </CIM>
*   Trying 172.17.0.1:8000...
* TCP_NODELAY set
* connect to 172.17.0.1 port 8000 failed: Connection refused
* Failed to connect to 172.17.0.1 port 8000: Connection refused
* Closing connection 0
curl: (7) Failed to connect to 172.17.0.1 port 8000: Connection refused

The pywbemlistener is defined as:

+--------+--------+----------+--------+---------------------+
| Name   |   Port | Scheme   |    PID | Created             |
|--------+--------+----------+--------+---------------------|
| lis1   |   8000 | http     | 503952 | 2023-04-23 14:48:34 |
+--------+--------+----------+--------+---------------------+

Looking at this with the netstat utility shows:

netstat -ln | grep 8000
Proto Recv-Q Send-Q  Local Address            Foreign Address         State
tcp              0            0  127.0.0.1:8000            0.0.0.0:*                     LISTEN

The "Local address" in the table above defines both the port and the host upon which pywbemlistener will listen. Thus we are limited to listening on the host server defined network because of the address 127.0.0.1 in the "Local Address" field, and not on any other WBEM servers. However, the standard way that docker containers send http(s) to the host system is through a Docker defined network (Typically defined as a bridge network Docker0 on linux systems. Thus the test environment network configurations with docker installed and using ifconfig utility shows the following:

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500   <=======================The Docker network
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:abff:fe91:2114  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ab:91:21:14  txqueuelen 0  (Ethernet)
        RX packets 95919  bytes 8550567 (8.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 116821  bytes 1518312864 (1.5 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 55930  bytes 9023539 (9.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 55930  bytes 9023539 (9.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethfb0a88b: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::9c3a:dcff:fef5:86ee  prefixlen 64  scopeid 0x20<link>
        ether 9e:3a:dc:f5:86:ee  txqueuelen 0  (Ethernet)
        RX packets 133  bytes 11924 (11.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 194  bytes 23755 (23.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500   <================ Host network
        inet 192.168.4.45  netmask 255.255.252.0  broadcast 192.168.7.255
        inet6 fd9b:8253:a423:1:92e7:d58e:c6b8:6e70  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::b59e:f5ba:cadc:c4c  prefixlen 64  scopeid 0x20<link>
        inet6 fd9b:8253:a423:1:2d5b:def1:bcd7:6f8c  prefixlen 64  scopeid 0x0<global>
        ether e4:70:b8:39:7f:38  txqueuelen 1000  (Ethernet)
        RX packets 10058058  bytes 11737220290 (11.7 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3279830  bytes 913855595 (913.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Since we have defined the host for the pywbemlistener as "localhost" in pywbemlistener function "cmd_listener_run()" and "cmd_listener_start()":

host = 'localhost'

I changed the line to:

host = ''

And we can not accept indications from any WBEM server on the pywbemlistener.

./send_indication.sh "http://172.17.0.1" -p 8000 -d 4
all http://172.17.0.1
fullurl=http://172.17.0.1:8000 key_opts=
Request payload:
<?xml version="1.0" encoding="utf-8" ?>
    <CIM CIMVERSION="2.0" DTDVERSION="2.4">
      <MESSAGE ID="42" PROTOCOLVERSION="1.4">
        <SIMPLEEXPREQ>
          <EXPMETHODCALL NAME="ExportIndication">
            <EXPPARAMVALUE NAME="NewIndication">
              <INSTANCE CLASSNAME="CIM_AlertIndication">
                <PROPERTY NAME="Severity" TYPE="string">
                  <VALUE>high</VALUE>
                </PROPERTY>
                <PROPERTY NAME="Sequence_Number" TYPE="string">
                  <VALUE>1</VALUE>
                </PROPERTY>
                <PROPERTY NAME="DELTA_TIME" TYPE="string">
                  <VALUE>0</VALUE>
                </PROPERTY>
              </INSTANCE>
            </EXPPARAMVALUE>
          </EXPMETHODCALL>
        </SIMPLEEXPREQ>
      </MESSAGE>
    </CIM>
*   Trying 172.17.0.1:8000...
* TCP_NODELAY set
* Connected to 172.17.0.1 (172.17.0.1) port 8000 (#0)
> POST / HTTP/1.1
> Host: 172.17.0.1:8000
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Type: text/xml
> Content-Length: 556
>
* upload completely sent off: 556 out of 556 bytes
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: pywbem-listener/1.6.1 BaseHTTP/0.6 Python/3.10.6
< Date: Sun, 23
``Apr 2023 20:45:55 GMT
< Content-Type: text/xml
< Content-Length: 207
< CIMExport: MethodResponse
<
<?xml version="1.0" encoding="utf-8" ?>
* Closing connection 0

CONCLUSION: We have an issue in pywbemlistener in defining parameters for a pywbemlistener that disallows sending from a container without more complex logistics than just using "localhost" as the host definition in the indication destination.

Note that there are several possible network types supported by docker including:

  1. Bridge network - The bridge networking for a docker container is to define a separate network (defaults to separate network Docker0 (default for ip4 is may be 172.17.0.x where the host is represented by 271.17.0.1 and each container is a member of this network (ex. 172.17.0.2, etc. that it appears that this setup of an additional network for the docker containers appears to be normal in Docker world. the .0.1 address is the address of the host. Thus indications from containers come from addresses like 172.17.0.2, etc. This also means that localhost within the container is different than localhost for the host system. Bridge is the default network type

  2. Host network - the containers share existing host network. This form is limited because the port-mapping parameters that are part of the current docker container (assign port 5988 to port 15988) definition are not allowed (we use port mapping to reassign the standard WBEM server ports to alternate ports so that host wbem servers can exist along with the container basedWBEM server.

Therefore, if bridge networking is used using "localhost" as the definition of the host for the listener does not work since indications are being sent from the Docker0 network, not from the host network and localhost is different in the container than in the host system. If host networking is used for the containers, the port reassignment of the WBEM servers cannot be used.

There is a further question in the use of the host IP address as part of the listener definition in that this parameter means that a particular listener rejects indications that are not from the defined IP address whereas if no IP address is defined for a listener indications are accepted from any WBEM server IP.

POSSIBLE SOLUTIONS;

  1. Just set the host parameter to "" for start and run commands. That means that the listener will accept indications from any host name on the ports defined.
  2. Define a more complex scheme whereby we can define the host IP address and/ port that the listener accepts or just the port for a specific listener. This could be resolved with a new optional general option 'host'. When defined it would be the definition of a WBEM server from which indication would be accepted for the listener being defined. Indications would be accepted only for this host. When not defined, indications would be accepted for any host on the defined port.

Either of the above solutions is clearly incompatible with the current code since the current code limits indications to be from the host machine "localhost" since the current code is to only accept indications from localhost.

KSchopmeyer commented 1 year ago

0.Closing as incomplete and possible incorrect. Will resubmit when confirmed. Later reopened.

The proposed fix is a: remove local host as the default listener host parameter (the host is the host name or IP address to which the listener binds.

The second part of this issue is that we need the flexibility to set the bind address as part of setting up a listener. Since a bind address of 0.0.0.0 forces the server to accept indications on any system network interfaces and that are addressed to any address known to the server, this is the logical default address.

However, it is also logical to allow the user to set a particular host IP or host name as the bind address so that indications could only be accepted when addressed to that particular host name or IP address.

Therefore we will add a new option to the pywbem listener and host commands to set the bind address for the listener being started/run. The value of this option could be either a host name or and IP address. This will be an optional option with the default value being '0.0.0.0' the IP address value for which the listener will accept indications on any network interface in the system and for any destination IP address.

KSchopmeyer commented 1 year ago

Closed this as incomplete after we fixed other issues in pywbemcli including:

  1. Update to new version of OpenPegasus container to fix issue where the OpenPegasus class defining the test indication send method was incorrect. Update to the docker container version 0.1.3 which fixed this issue. issue #1305
  2. An issue where we were forcing localhost in pywbemlistener start as the bind address for the listener container rather than a public host name or the wild card address.
KSchopmeyer commented 1 year ago

Fixed with PR #1305 where we added option to set bind_addr on listeners and specifically eliminated that forced the bind_address (host parameter) to "localhost" which was causing us to only accept indications that sent by the localhost.

KSchopmeyer commented 1 year ago

Closing this pr as complete.