diff --git a/.github/docker/unit-tests/Dockerfile.unit-tests-alma8 b/.github/docker/unit-tests/Dockerfile.unit-tests-alma8 index 9406f2ab3..ff88e1078 100644 --- a/.github/docker/unit-tests/Dockerfile.unit-tests-alma8 +++ b/.github/docker/unit-tests/Dockerfile.unit-tests-alma8 @@ -46,7 +46,7 @@ gpgcheck=1\n\ gpgkey=https://yum-gpg.centreon.com/RPM-GPG-KEY-CES\n'\ >> /etc/yum.repos.d/centreon-plugins.repo -dnf install -y gcc make cpan perl-Test2-Suite.noarch perl-Test2-Plugin-NoWarnings.noarch 'perl(Authen::Radius)' 'perl(Convert::Binary::C)' 'perl(Crypt::OpenSSL::RSA)' 'perl(Data::Dumper)' 'perl(Date::Parse)' 'perl(DateTime)' 'perl(DateTime::Duration)' 'perl(DateTime-Format-Duration-ISO8601)' 'perl(DateTime::Format::Strptime)' 'perl(DBD::mysql)' 'perl(DBD::ODBC)' 'perl(DBD::Pg)' 'perl(DBD::Sybase)' 'perl(DBI)' 'perl(Device::Modbus::RTU::Client)' 'perl(Device::Modbus::TCP::Client)' 'perl(Digest::CRC)' 'perl(Digest::MD5)' 'perl(Digest::SHA)' 'perl(Email::MIME)' 'perl(Email::Sender)' 'perl(Email::Send::SMTP::Gmail)' 'perl(Email::Simple)' 'perl(File::Basename)' 'perl(Filesys::SmbClient)' 'perl(Hash::Ordered)' 'perl(HTML::Template)' 'perl(IO::Select)' 'perl(IO::Socket)' 'perl(IO::Socket::INET)' 'perl(IO::Socket::INET6)' 'perl(IO::Socket::SSL)' 'perl(JMX::Jmx4Perl)' 'perl(JSON)' 'perl(JSON::Path)' 'perl(JSON::WebToken)' 'perl(JSON::XS)' 'perl(Libssh::Session)' 'perl-Mail-IMAPClient' 'perl(MIME::Base64)' 'perl(MongoDB)' 'perl(NetAddr::IP)' 'perl(Net::DHCP::Constants)' 'perl(Net::DHCP::Packet)' 'perl(Net::DNS)' 'perl(Net::FTP)' 'perl(Net::FTPSSL)' 'perl(Net::LDAP)' 'perl(Net::MQTT::Simple)' 'perl(Net::NTP)' 'perl(Net::SSLeay)' 'perl(Net::Subnet)' 'perl(Net::Telnet)' 'perl(Net::TFTP)' 'perl(openwsman)' 'perl(Pod::Parser)' 'perl(POSIX)' 'perl(Redis)' 'perl(RRDs)' 'perl(SNMP)' 'perl(Socket)' 'perl(Text::CSV)' 'perl(Time::HiRes)' 'perl(URI::Encode)' 'perl(URI::Escape)' 'perl(UUID)' 'perl(WWW::Selenium)' 'perl(XML::LibXML)' 'perl(XML::LibXML::Simple)' 'perl(XML::Simple)' 'perl(XML::XPath)' 'perl(ZMQ::LibZMQ4)' 'perl(Data::UUID)' +dnf install -y gcc make cpan perl-Test2-Suite.noarch perl-Test2-Plugin-NoWarnings.noarch 'perl(Authen::Radius)' 'perl(Convert::Binary::C)' 'perl(Crypt::OpenSSL::RSA)' 'perl(Data::Dumper)' 'perl(Date::Parse)' 'perl(DateTime)' 'perl(DateTime::Duration)' 'perl(DateTime-Format-Duration-ISO8601)' 'perl(DateTime::Format::Strptime)' 'perl(DBD::mysql)' 'perl(DBD::ODBC)' 'perl(DBD::Pg)' 'perl(DBD::Sybase)' 'perl(DBI)' 'perl(Device::Modbus::RTU::Client)' 'perl(Device::Modbus::TCP::Client)' 'perl(Digest::CRC)' 'perl(Digest::MD5)' 'perl(Digest::SHA)' 'perl(Email::MIME)' 'perl(Email::Sender)' 'perl(Email::Send::SMTP::Gmail)' 'perl(Email::Simple)' 'perl(File::Basename)' 'perl(Filesys::SmbClient)' 'perl(Hash::Ordered)' 'perl(HTML::Template)' 'perl(IO::Select)' 'perl(IO::Socket)' 'perl(IO::Socket::INET)' 'perl(IO::Socket::INET6)' 'perl(IO::Socket::SSL)' 'perl(JMX::Jmx4Perl)' 'perl(JSON)' 'perl(JSON::Path)' 'perl(JSON::WebToken)' 'perl(JSON::XS)' 'perl(Libssh::Session)' 'perl-Mail-IMAPClient' 'perl(MIME::Base64)' 'perl(MongoDB)' 'perl(NetAddr::IP)' 'perl(Net::DHCP::Constants)' 'perl(Net::DHCP::Packet)' 'perl(Net::DNS)' 'perl(Net::FTP)' 'perl(Net::FTPSSL)' 'perl(Net::LDAP)' 'perl(Net::MQTT::Simple)' 'perl(Net::NTP)' 'perl(Net::SSLeay)' 'perl(Net::Subnet)' 'perl(Net::Telnet)' 'perl(Net::TFTP)' 'perl(openwsman)' 'perl(Pod::Parser)' 'perl(POSIX)' 'perl(Redis)' 'perl(RRDs)' 'perl(SNMP)' 'perl(Socket)' 'perl(Text::CSV)' 'perl(Time::HiRes)' 'perl(URI::Encode)' 'perl(URI::Escape)' 'perl(UUID)' 'perl(WWW::Selenium)' 'perl(XML::LibXML)' 'perl(XML::LibXML::Simple)' 'perl(XML::Simple)' 'perl(XML::XPath)' 'perl(ZMQ::LibZMQ4)' 'perl(Data::UUID)' 'perl(String::ShellQuote)' # this image is used by centreon-perl-libs unit test and centreon-gorgone unit tests. dnf -y install 'perl(Crypt::OpenSSL::AES)' 'perl-Net-Curl' 'perl(YAML::XS)' 'perl(Hash::Merge)' 'perl(Clone)' 'perl(CryptX)' 'perl(JSON::XS)' 'perl(JSON::PP)' 'perl(Digest::MD5::File)' dnf -y install 'perl(Hash::Merge)' 'perl(YAML::XS)' 'perl(ZMQ::FFI)' 'perl-CryptX' 'perl(EV)' 'perl(RRDs)' 'perl(DBI)' 'perl(DBD::SQLite)' 'perl(HTTP::Daemon)' 'perl(HTTP::Daemon::SSL)' 'perl(NetAddr::IP)' 'perl(Mojolicious)' 'perl(Mojo::IOLoop::Signal)' 'perl(Net::Curl)' 'perl(EV)' diff --git a/.github/docker/unit-tests/Dockerfile.unit-tests-alma9 b/.github/docker/unit-tests/Dockerfile.unit-tests-alma9 index e8f9375bb..00e4d666a 100644 --- a/.github/docker/unit-tests/Dockerfile.unit-tests-alma9 +++ b/.github/docker/unit-tests/Dockerfile.unit-tests-alma9 @@ -45,7 +45,8 @@ enabled=1\n\ gpgcheck=1\n\ gpgkey=https://yum-gpg.centreon.com/RPM-GPG-KEY-CES\n'\ >> /etc/yum.repos.d/centreon-plugins.repo -dnf install -y make cpan perl-Test2-Suite.noarch 'perl(Authen::Radius)' 'perl(Convert::Binary::C)' 'perl(Crypt::OpenSSL::RSA)' 'perl(Data::Dumper)' 'perl(Date::Parse)' 'perl(DateTime)' 'perl(DateTime::Duration)' 'perl(DateTime-Format-Duration-ISO8601)' 'perl(DateTime::Format::Strptime)' 'perl(DBD::mysql)' 'perl(DBD::ODBC)' 'perl(DBD::Pg)' 'perl(DBD::Sybase)' 'perl(DBI)' 'perl(Device::Modbus::RTU::Client)' 'perl(Device::Modbus::TCP::Client)' 'perl(Digest::CRC)' 'perl(Digest::MD5)' 'perl(Digest::SHA)' 'perl(Email::MIME)' 'perl(Email::Sender)' 'perl(Email::Send::SMTP::Gmail)' 'perl(Email::Simple)' 'perl(File::Basename)' 'perl(Filesys::SmbClient)' 'perl(Hash::Ordered)' 'perl(HTML::Template)' 'perl(IO::Select)' 'perl(IO::Socket)' 'perl(IO::Socket::INET)' 'perl(IO::Socket::INET6)' 'perl(IO::Socket::SSL)' 'perl(JMX::Jmx4Perl)' 'perl(JSON)' 'perl(JSON::Path)' 'perl(JSON::WebToken)' 'perl(JSON::XS)' 'perl(Libssh::Session)' 'perl-Mail-IMAPClient' 'perl(MIME::Base64)' 'perl(MongoDB)' 'perl(NetAddr::IP)' 'perl(Net::DHCP::Constants)' 'perl(Net::DHCP::Packet)' 'perl(Net::DNS)' 'perl(Net::FTP)' 'perl(Net::FTPSSL)' 'perl(Net::LDAP)' 'perl(Net::MQTT::Simple)' 'perl(Net::NTP)' 'perl(Net::SSLeay)' 'perl(Net::Subnet)' 'perl(Net::Telnet)' 'perl(Net::TFTP)' 'perl(openwsman)' 'perl(Pod::Parser)' 'perl(POSIX)' 'perl(Redis)' 'perl(RRDs)' 'perl(SNMP)' 'perl(Socket)' 'perl(Text::CSV)' 'perl(Time::HiRes)' 'perl(URI::Encode)' 'perl(URI::Escape)' 'perl(UUID)' 'perl(WWW::Selenium)' 'perl(XML::LibXML)' 'perl(XML::LibXML::Simple)' 'perl(XML::Simple)' 'perl(XML::XPath)' 'perl(ZMQ::LibZMQ4)' 'perl(Data::UUID)' +dnf install -y make cpan perl-Test2-Suite.noarch 'perl(Authen::Radius)' 'perl(Convert::Binary::C)' 'perl(Crypt::OpenSSL::RSA)' 'perl(Data::Dumper)' 'perl(Date::Parse)' 'perl(DateTime)' 'perl(DateTime::Duration)' 'perl(DateTime-Format-Duration-ISO8601)' 'perl(DateTime::Format::Strptime)' 'perl(DBD::mysql)' 'perl(DBD::ODBC)' 'perl(DBD::Pg)' 'perl(DBD::Sybase)' 'perl(DBI)' 'perl(Device::Modbus::RTU::Client)' 'perl(Device::Modbus::TCP::Client)' 'perl(Digest::CRC)' 'perl(Digest::MD5)' 'perl(Digest::SHA)' 'perl(Email::MIME)' 'perl(Email::Sender)' 'perl(Email::Send::SMTP::Gmail)' 'perl(Email::Simple)' 'perl(File::Basename)' 'perl(Filesys::SmbClient)' 'perl(Hash::Ordered)' 'perl(HTML::Template)' 'perl(IO::Select)' 'perl(IO::Socket)' 'perl(IO::Socket::INET)' 'perl(IO::Socket::INET6)' 'perl(IO::Socket::SSL)' 'perl(JMX::Jmx4Perl)' 'perl(JSON)' 'perl(JSON::Path)' 'perl(JSON::WebToken)' 'perl(JSON::XS)' 'perl(Libssh::Session)' 'perl-Mail-IMAPClient' 'perl(MIME::Base64)' 'perl(MongoDB)' 'perl(NetAddr::IP)' 'perl(Net::DHCP::Constants)' 'perl(Net::DHCP::Packet)' 'perl(Net::DNS)' 'perl(Net::FTP)' 'perl(Net::FTPSSL)' 'perl(Net::LDAP)' 'perl(Net::MQTT::Simple)' 'perl(Net::NTP)' 'perl(Net::SSLeay)' 'perl(Net::Subnet)' 'perl(Net::Telnet)' 'perl(Net::TFTP)' 'perl(openwsman)' 'perl(Pod::Parser)' 'perl(POSIX)' 'perl(Redis)' 'perl(RRDs)' 'perl(SNMP)' 'perl(Socket)' 'perl(Text::CSV)' 'perl(Time::HiRes)' 'perl(URI::Encode)' 'perl(URI::Escape)' 'perl(UUID)' 'perl(WWW::Selenium)' 'perl(XML::LibXML)' 'perl(XML::LibXML::Simple)' 'perl(XML::Simple)' 'perl(XML::XPath)' 'perl(ZMQ::LibZMQ4)' 'perl(Data::UUID)' 'perl(String::ShellQuote)' + # this image is used by centreon-perl-libs unit test and centreon-gorgone unit tests. dnf -y install 'perl(Crypt::OpenSSL::AES)' 'perl-Net-Curl' 'perl(YAML::XS)' 'perl(Hash::Merge)' 'perl(Clone)' 'perl(CryptX)' 'perl(JSON::XS)' 'perl(JSON::PP)' 'perl(Digest::MD5::File)' dnf -y install 'perl(ZMQ::FFI)' 'perl(EV)' 'perl(RRDs)' 'perl(DBI)' 'perl(DBD::SQLite)' 'perl(HTTP::Daemon)' 'perl(HTTP::Daemon::SSL)' 'perl(NetAddr::IP)' 'perl(Mojolicious)' 'perl(Mojo::IOLoop::Signal)' 'perl(Net::Curl)' diff --git a/.github/docker/unit-tests/Dockerfile.unit-tests-bookworm b/.github/docker/unit-tests/Dockerfile.unit-tests-bookworm index 4a809c44a..70aadd01d 100644 --- a/.github/docker/unit-tests/Dockerfile.unit-tests-bookworm +++ b/.github/docker/unit-tests/Dockerfile.unit-tests-bookworm @@ -23,7 +23,7 @@ echo "deb https://packages.centreon.com/apt-plugins-testing/ bookworm main" | te echo "deb https://packages.centreon.com/apt-plugins-unstable/ bookworm main" | tee -a /etc/apt/sources.list.d/centreon-plugins.list wget -O- https://apt-key.centreon.com | gpg --dearmor | tee /etc/apt/trusted.gpg.d/centreon.gpg > /dev/null 2>&1 apt-get update -apt-get -y install libtest2-harness-perl libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl perl perl-modules +apt-get -y install libtest2-harness-perl libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl perl perl-modules libstring-shellquote-perl # this image is used by centreon-perl-libs unit test and centreon-gorgone unit tests. apt-get -y install libcrypt-openssl-aes-perl libnet-curl-perl libyaml-libyaml-perl libhash-merge-perl libclone-choose-perl libcryptx-perl libjson-xs-perl libjson-pp-perl librrds-perl libdbi-perl libdbd-sqlite3-perl libhttp-daemon-perl libhttp-daemon-ssl-perl libnetaddr-ip-perl libmojolicious-perl libmojo-ioloop-signal-perl libnet-curl-perl libev-perl apt-get -y install libhash-merge-perl libyaml-libyaml-perl libzmq-ffi-perl libcryptx-perl libev-perl libdigest-md5-file-perl diff --git a/.github/docker/unit-tests/Dockerfile.unit-tests-bullseye b/.github/docker/unit-tests/Dockerfile.unit-tests-bullseye index c96ccd797..73539ee64 100644 --- a/.github/docker/unit-tests/Dockerfile.unit-tests-bullseye +++ b/.github/docker/unit-tests/Dockerfile.unit-tests-bullseye @@ -23,7 +23,7 @@ echo "deb https://packages.centreon.com/apt-plugins-testing/ bullseye main" | te echo "deb https://packages.centreon.com/apt-plugins-unstable/ bullseye main" | tee -a /etc/apt/sources.list.d/centreon-plugins.list wget -O- https://apt-key.centreon.com | gpg --dearmor | tee /etc/apt/trusted.gpg.d/centreon.gpg > /dev/null 2>&1 apt-get update -apt-get -y install gcc make libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl perl perl-modules libdata-uuid-perl libdigest-md5-file-perl +apt-get -y install gcc make libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl perl perl-modules libdata-uuid-perl libdigest-md5-file-perl libstring-shellquote-perl # this image is used by centreon-perl-libs unit test and centreon-gorgone unit tests. apt-get -y install libzmq-ffi-perl libcpanel-json-xs-perl libcrypt-openssl-aes-perl libnet-curl-perl libyaml-libyaml-perl libhash-merge-perl libclone-choose-perl libcryptx-perl libjson-xs-perl libjson-pp-perl librrds-perl libdbi-perl libdbd-sqlite3-perl libhttp-daemon-perl libhttp-daemon-ssl-perl libnetaddr-ip-perl libmojolicious-perl libmojo-ioloop-signal-perl libnet-curl-perl libev-perl libdigest-md5-file-perl apt-get -y install git mariadb-client diff --git a/.github/docker/unit-tests/Dockerfile.unit-tests-jammy b/.github/docker/unit-tests/Dockerfile.unit-tests-jammy index 04e53f1d1..5609ffd1c 100644 --- a/.github/docker/unit-tests/Dockerfile.unit-tests-jammy +++ b/.github/docker/unit-tests/Dockerfile.unit-tests-jammy @@ -25,7 +25,7 @@ echo "deb https://packages.centreon.com/ubuntu-plugins-unstable/ jammy main" | t wget -O- https://apt-key.centreon.com | gpg --dearmor | tee /etc/apt/trusted.gpg.d/centreon.gpg > /dev/null 2>&1 apt-get update -apt-get -y install gcc make libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjmx4perl-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl libzmq-libzmq4-perl perl perl-modules +apt-get -y install gcc make libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjmx4perl-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl libzmq-libzmq4-perl perl perl-modules libstring-shellquote-perl # this image is used by centreon-perl-libs unit test and centreon-gorgone unit tests. apt-get -y install libcrypt-openssl-aes-perl libnet-curl-perl libyaml-libyaml-perl libhash-merge-perl libclone-choose-perl libcryptx-perl libjson-xs-perl libjson-pp-perl librrds-perl libdbi-perl libdbd-sqlite3-perl libhttp-daemon-perl libhttp-daemon-ssl-perl libnetaddr-ip-perl libmojolicious-perl libmojo-ioloop-signal-perl libnet-curl-perl libev-perl libdigest-md5-file-perl apt-get -y install git mariadb-client diff --git a/.github/docker/unit-tests/Dockerfile.unit-tests-noble b/.github/docker/unit-tests/Dockerfile.unit-tests-noble index 90049c6a6..5d597d3e7 100644 --- a/.github/docker/unit-tests/Dockerfile.unit-tests-noble +++ b/.github/docker/unit-tests/Dockerfile.unit-tests-noble @@ -25,7 +25,7 @@ echo "deb https://packages.centreon.com/ubuntu-plugins-unstable/ noble main" | t wget -O- https://apt-key.centreon.com | gpg --dearmor | tee /etc/apt/trusted.gpg.d/centreon.gpg > /dev/null 2>&1 apt-get update -apt-get -y install gcc make libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjmx4perl-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl libzmq-libzmq4-perl perl perl-modules +apt-get -y install gcc make libtest2-plugin-nowarnings-perl libauthen-radius-perl libconvert-binary-c-perl libcrypt-openssl-rsa-perl libdata-dump-perl libdatetime-format-dateparse-perl libdatetime-format-strptime-perl libdatetime-perl libdbd-mysql-perl libdbd-odbc-perl libdbd-pg-perl libdbd-sybase-perl libdbi-perl libdigest-crc-perl libdigest-md5-perl libdigest-sha-perl libemail-mime-perl libemail-sender-perl libemail-send-smtp-gmail-perl libfilesys-smbclient-perl libhtml-template-perl libio-socket-inet6-perl libio-socket-ip-perl libjmx4perl-perl libjson-maybexs-perl libjson-perl libjson-webtoken-perl libmail-imapclient-perl libmime-base64-perl libmongodb-perl libnet-dhcp-perl libnet-dns-perl libnet-ldap-perl libnet-mqtt-simple-perl libnet-ntp-perl libnet-ssleay-perl libnet-subnet-perl libnet-telnet-perl libnet-tftp-perl libopenwsman-perl libredis-perl librrds-perl libsnmp-perl libsocket-perl libssh-session-perl libtest-www-selenium-perl libtext-csv-perl libtime-hires-perl libtime-parsedate-perl libuuid-perl libxml-libxml-perl libxml-libxml-simple-perl libxml-simple-perl libxml-xpath-perl libzmq-libzmq4-perl perl perl-modules libstring-shellquote-perl # this image is used by centreon-perl-libs unit test and centreon-gorgone unit tests. apt-get -y install libcrypt-openssl-aes-perl libnet-curl-perl libyaml-libyaml-perl libhash-merge-perl libclone-choose-perl libcryptx-perl libjson-xs-perl libjson-pp-perl librrds-perl libdbi-perl libdbd-sqlite3-perl libhttp-daemon-perl libhttp-daemon-ssl-perl libnetaddr-ip-perl libmojolicious-perl libmojo-ioloop-signal-perl libnet-curl-perl libev-perl libdigest-md5-file-perl apt-get -y install git mariadb-client diff --git a/.github/packaging/centreon-plugin.yaml.template b/.github/packaging/centreon-plugin.yaml.template index a0cc5cfec..73fc1910d 100644 --- a/.github/packaging/centreon-plugin.yaml.template +++ b/.github/packaging/centreon-plugin.yaml.template @@ -53,6 +53,7 @@ overrides: perl(FindBin), perl(lib), perl(sort), + perl(String::ShellQuote), @RPM_DEPENDENCIES@ ] conflicts: @@ -80,6 +81,7 @@ overrides: libkeepass-reader-perl, libdatetime-perl, libxml-libxml-perl, + libstring-shellquote-perl, @DEB_DEPENDENCIES@ ] conflicts: diff --git a/.github/scripts/plugins-source.container.pl b/.github/scripts/plugins-source.container.pl index 0481e03eb..b93a4757f 100644 --- a/.github/scripts/plugins-source.container.pl +++ b/.github/scripts/plugins-source.container.pl @@ -66,6 +66,7 @@ foreach my $plugin (@plugins) { File::Path::remove_tree('lib'); File::Path::make_path('lib'); my @common_files = ( + 'centreon/plugins/curllogger.pm', 'centreon/plugins/http.pm', 'centreon/plugins/misc.pm', 'centreon/plugins/mode.pm', diff --git a/src/centreon/plugins/backend/http/curl.pm b/src/centreon/plugins/backend/http/curl.pm index 5a314429f..769aa3be3 100644 --- a/src/centreon/plugins/backend/http/curl.pm +++ b/src/centreon/plugins/backend/http/curl.pm @@ -39,6 +39,8 @@ sub new { $self->{output} = $options{output}; + $self->{curl_log} = $options{curl_logger}; + return $self; } @@ -158,23 +160,39 @@ sub set_method { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => undef); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPGET'), parameter => 1); + my $skip_log_post = 0; + # POST inferred by CURLOPT_POSTFIELDS if ($options{content_type_forced} == 1) { - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => $options{request}->{query_form_post}) - if (defined($options{request}->{query_form_post})); + if (defined($options{request}->{query_form_post})) { + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => $options{request}->{query_form_post}); + $self->{curl_log}->log("--data-raw", $options{request}->{query_form_post}); + $skip_log_post = 1; + } } elsif (defined($options{request}->{post_params})) { my $uri_post = URI->new(); $uri_post->query_form($options{request}->{post_params}); - push @{$options{headers}}, 'Content-Type: application/x-www-form-urlencoded'; + my $urlencodedheader = 'Content-Type: application/x-www-form-urlencoded'; + push @{$options{headers}}, $urlencodedheader; + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POSTFIELDS'), parameter => $uri_post->query); + $self->{curl_log}->log("-H", $urlencodedheader); + + $self->{curl_log}->log("--data-raw", $uri_post->query); + $skip_log_post = 1; } if ($options{request}->{method} eq 'GET') { - return ; + # no curl_log call because GET is the default value + return; } if ($options{request}->{method} eq 'POST') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_POST'), parameter => 1); + $self->{curl_log}->log('-X', $options{request}->{method}) unless $skip_log_post; + return; } + + $self->{curl_log}->log('-X', $options{request}->{method}); if ($options{request}->{method} eq 'PUT') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CUSTOMREQUEST'), parameter => $options{request}->{method}); } @@ -192,25 +210,38 @@ sub set_auth { if (defined($options{request}->{credentials})) { if (defined($options{request}->{basic})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_BASIC')); + $self->{curl_log}->log('--basic'); } elsif (defined($options{request}->{ntlmv2})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_NTLM')); + $self->{curl_log}->log('--ntlm'); } elsif (defined($options{request}->{digest})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_DIGEST')); + $self->{curl_log}->log('--digest'); }else { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPAUTH'), parameter => $self->{constant_cb}->(name => 'CURLAUTH_ANY')); + $self->{curl_log}->log('--anyauth'); } - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_USERPWD'), parameter => $options{request}->{username} . ':' . $options{request}->{password}); + my $userpassword = $options{request}->{username} . ':' . $options{request}->{password}; + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_USERPWD'), parameter => $userpassword); + $self->{curl_log}->log('--user', $userpassword); } if (defined($options{request}->{cert_file}) && $options{request}->{cert_file} ne '') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERT'), parameter => $options{request}->{cert_file}); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLKEY'), parameter => $options{request}->{key_file}); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_KEYPASSWD'), parameter => $options{request}->{cert_pwd}); + + $self->{curl_log}->log('--cert', $options{request}->{cert_file}); + $self->{curl_log}->log('--key', $options{request}->{key_file}); + $self->{curl_log}->log('--pass', $options{request}->{cert_pwd}) if defined $options{request}->{cert_pwd} && $options{request}->{cert_pwd} ne ''; } - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERTTYPE'), parameter => "PEM"); if (defined($options{request}->{cert_pkcs12})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERTTYPE'), parameter => "P12"); + $self->{curl_log}->log('--cert-type', 'p12'); + } else { + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSLCERTTYPE'), parameter => "PEM"); + # no curl_log call because PEM is the default value } } @@ -234,6 +265,9 @@ sub set_form { $args{ $self->{constant_cb}->(name => 'CURLFORM_COPYCONTENTS()') } = $_->{copycontents} if (defined($_->{copycontents})); $form->add(%args); + + $self->{curl_log}->log("--form-string", $_->{copyname}."=".$_->{copycontents}) + if defined($_->{copyname}) && defined($_->{copycontents}); } $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_HTTPPOST()'), parameter => $form); @@ -244,6 +278,7 @@ sub set_proxy { if (defined($options{request}->{proxyurl}) && $options{request}->{proxyurl} ne '') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_PROXY'), parameter => $options{request}->{proxyurl}); + $self->{curl_log}->log("--proxy", $options{request}->{proxyurl}); } if (defined($options{request}->{proxypac}) && $options{request}->{proxypac} ne '') { @@ -261,14 +296,35 @@ sub set_extra_curl_opt { $key = centreon::plugins::misc::trim($key); if (!defined($entries->{$key})) { - $entries->{$key} = { val => [], force_array => 0 }; + $entries->{$key} = { val => [], constants => [], force_array => 0 }; } $value = centreon::plugins::misc::trim($value); + + # Here we want to convert a string containing curl options into a single value or into + # an array of values depending on whether it begins with '[' and ends with ']'. + # We also remove the quotes. + # for example: + # + # $opt = ["CURLOPT_SSL_VERIFYPEER =>[opt1,'opt2','opt3']"]; + # is converted to a Perl array like this: + # $VAR1 = [ + # 'opt1', + # 'opt2', + # 'opt3' + # ]; + # + # $opt = [ "CURLOPT_SSL_VERIFYPEER => 'opt1'" ]; + # is converted to: + # $VAR1 = 'opt1'; if ($value =~ /^\[(.*)\]$/) { $entries->{$key}->{force_array} = 1; $value = centreon::plugins::misc::trim($1); + push @{$entries->{$key}->{constants}}, map { $_ = centreon::plugins::misc::trim($_); s/^'(.*)'$/$1/; $_ } split ',', $value; + } else { + push @{$entries->{$key}->{constants}}, $value =~ /^'(.*)'$/ ? $1 : $value; } + if ($value =~ /^CURLOPT|CURL/) { $value = $self->{constant_cb}->(name => $value); } @@ -278,15 +334,26 @@ sub set_extra_curl_opt { foreach (keys %$entries) { my $key = $_; + + if ($self->{curl_log}->is_enabled()) { + $self->{curl_log}->convert_curlopt_to_cups_parameter( + key => $key, + parameter => $entries->{$key}->{constants}, + ); + } + if (/^CURLOPT|CURL/) { $key = $self->{constant_cb}->(name => $_); } + my $parameter; if ($entries->{$_}->{force_array} == 1 || scalar(@{$entries->{$_}->{val}}) > 1) { - $self->curl_setopt(option => $key, parameter => $entries->{$_}->{val}); + $parameter = $entries->{$_}->{val}; } else { - $self->curl_setopt(option => $key, parameter => pop @{$entries->{$_}->{val}}); + $parameter = pop @{$entries->{$_}->{val}}; } + $self->curl_setopt(option => $key, parameter => $parameter); + } } @@ -315,29 +382,13 @@ sub cb_get_header { sub request { my ($self, %options) = @_; + # Enable curl logger when debug mode is on + $self->{curl_log}->init( enabled => $self->{output}->is_debug() ); + if (!defined($self->{curl_easy})) { $self->{curl_easy} = Net::Curl::Easy->new(); } - if ($self->{output}->is_debug()) { - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_DEBUGFUNCTION'), parameter => \&cb_debug); - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_DEBUGDATA'), parameter => $self); - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_VERBOSE'), parameter => 1); - } - - if (defined($options{request}->{timeout}) && $options{request}->{timeout} =~ /\d/) { - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_TIMEOUT'), parameter => $options{request}->{timeout}); - } - if (defined($options{request}->{cookies_file})) { - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_COOKIEFILE'), parameter => $options{request}->{cookies_file}); - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_COOKIEJAR'), parameter => $options{request}->{cookies_file}); - } - - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FOLLOWLOCATION'), parameter => 1); - if (defined($options{request}->{no_follow})) { - $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FOLLOWLOCATION'), parameter => 0); - } - my $url; if (defined($options{request}->{full_url})) { $url = $options{request}->{full_url}; @@ -347,14 +398,6 @@ sub request { $url = $options{request}->{proto}. "://" . $options{request}->{hostname} . $options{request}->{url_path}; } - if (defined($options{request}->{http_peer_addr}) && $options{request}->{http_peer_addr} ne '') { - $url =~ /^(?:http|https):\/\/(.*?)(\/|\:|$)/; - $self->{curl_easy}->setopt( - $self->{constant_cb}->(name => 'CURLOPT_RESOLVE'), - [$1 . ':' . $options{request}->{port_force} . ':' . $options{request}->{http_peer_addr}] - ); - } - my $uri = URI->new($url); if (defined($options{request}->{get_params})) { $uri->query_form($options{request}->{get_params}); @@ -362,13 +405,54 @@ sub request { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_URL'), parameter => $uri); + $self->{curl_log}->log($uri); + + if ($self->{output}->is_debug()) { + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_DEBUGFUNCTION'), parameter => \&cb_debug); + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_DEBUGDATA'), parameter => $self); + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_VERBOSE'), parameter => 1); + + $self->{curl_log}->log('--verbose'); + } + + if (defined($options{request}->{timeout}) && $options{request}->{timeout} =~ /\d/) { + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_TIMEOUT'), parameter => $options{request}->{timeout}); + $self->{curl_log}->log("--max-time", $options{request}->{timeout}); + } + + if (defined($options{request}->{cookies_file})) { + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_COOKIEFILE'), parameter => $options{request}->{cookies_file}); + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_COOKIEJAR'), parameter => $options{request}->{cookies_file}); + $self->{curl_log}->log('--cookie', $options{request}->{cookies_file}); + $self->{curl_log}->log('--cookie-jar', $options{request}->{cookies_file}); + } + + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FOLLOWLOCATION'), parameter => 1); + if (defined($options{request}->{no_follow})) { + $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FOLLOWLOCATION'), parameter => 0); + } else { + $self->{curl_log}->log('-L'); + } + + if (defined($options{request}->{http_peer_addr}) && $options{request}->{http_peer_addr} ne '') { + $url =~ /^(?:http|https):\/\/(.*?)(\/|\:|$)/; + my $resolve = $1 . ':' . $options{request}->{port_force} . ':' . $options{request}->{http_peer_addr}; + $self->{curl_easy}->setopt( + $self->{constant_cb}->(name => 'CURLOPT_RESOLVE'), + [$resolve] + ); + $self->{curl_log}->log('--resolve', $resolve); + } + my $headers = []; my $content_type_forced = 0; foreach my $key (keys %{$options{request}->{headers}}) { - push @$headers, $key . ':' . (defined($options{request}->{headers}->{$key}) ? $options{request}->{headers}->{$key} : ''); + my $header = $key . ':' . (defined($options{request}->{headers}->{$key}) ? $options{request}->{headers}->{$key} : ''); + push @$headers, $header; if ($key =~ /content-type/i) { $content_type_forced = 1; } + $self->{curl_log}->log("-H", $header); } $self->set_method(%options, content_type_forced => $content_type_forced, headers => $headers); @@ -383,16 +467,17 @@ sub request { if (defined($options{request}->{cacert_file}) && $options{request}->{cacert_file} ne '') { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CAINFO'), parameter => $options{request}->{cacert_file}); + $self->{curl_log}->log('--cacert', $options{request}->{cacert_file}); } if (defined($options{request}->{insecure})) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSL_VERIFYPEER'), parameter => 0); $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_SSL_VERIFYHOST'), parameter => 0); + $self->{curl_log}->log('--insecure'); } $self->set_auth(%options); $self->set_proxy(%options); $self->set_extra_curl_opt(%options); - $self->{response_body} = ''; $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_FILE'), parameter => \$self->{response_body}); $self->{nheaders} = 0; @@ -402,9 +487,15 @@ sub request { if (defined($options{request}->{certinfo}) && $options{request}->{certinfo} == 1) { $self->curl_setopt(option => $self->{constant_cb}->(name => 'CURLOPT_CERTINFO'), parameter => 1); + # no curl_log call because there is no equivalent in command line } $self->{response_code} = undef; + + if ($self->{curl_log}->is_enabled()) { + $self->{output}->output_add(long_msg => 'curl request [curl backend]: ' . $self->{curl_log}->get_log()); + } + eval { $self->{curl_easy}->perform(); }; diff --git a/src/centreon/plugins/curllogger.pm b/src/centreon/plugins/curllogger.pm new file mode 100644 index 000000000..b9700d25d --- /dev/null +++ b/src/centreon/plugins/curllogger.pm @@ -0,0 +1,126 @@ +# +# Copyright 2025 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::plugins::curllogger; + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + $self->{log_as_curl} = []; + $self->{is_log_as_curl} = 0; + + # As this is only used for debugging purposes, we disable it if the ShellQuote + # module is missing + eval "use String::ShellQuote"; + if ($@) { + $self->{is_log_as_curl} = -1; + } + + $self; +} + +sub init { + my ($self, %options) = @_; + + $self->{log_as_curl} = []; + return if $self->{is_log_as_curl} == -1; + + $self->{is_log_as_curl} = $options{enabled} || 0; +} + +sub is_enabled { + my ($self) = @_; + + return $self->{is_log_as_curl} == 1; +} + +sub log { + my ($self, @params) = @_; + + return unless $self->{is_log_as_curl} == 1 && @params; + + push @{$self->{log_as_curl}}, shell_quote(@params); +} + +sub get_log { + my ($self) = @_; + + return "curl ".join ' ', @{$self->{log_as_curl}}; +} + +# Conversion of some parameters manually passed to the set_extra_curl_opt function +# into their command-line equivalents. Only the parameters used in the plugin code +# are handled. If new parameters are added, this hash must be updated. +# The hash contains curl parameters CURLOPT_*. Its keys map to either a hash when +# multiple values are handled, or directly to an array when only one response is +# supported. The placeholder is replaced by the provided value. +# Eg: "CURLOPT_POSTREDIR => CURL_REDIR_POST_ALL" will produce: --post301 --post302 --post303 +# "CURLOPT_SSL_VERIFYPEER => 0" will produce: --insecure +# "CURLOPT_AWS_SIGV4 => 'osc'" will produce: --aws-sigv4 osc +our %curlopt_to_parameter = ( + 'CURLOPT_POSTREDIR' => { 'CURL_REDIR_POST_ALL' => [ '--post301', '--post302', '--post303', ], + 'CURL_REDIR_POST_301' => [ '--post301' ], + 'CURL_REDIR_POST_302' => [ '--post302' ], + 'CURL_REDIR_POST_303' => [ '--post303' ], + }, + 'CURLOPT_SSLVERSION' => { 'CURL_SSLVERSION_TLSv1_0' => [ '--tlsv1.0' ], + 'CURL_SSLVERSION_TLSv1_1' => [ '--tlsv1.1' ], + 'CURL_SSLVERSION_TLSv1_2' => [ '--tlsv1.2' ], + 'CURL_SSLVERSION_TLSv1_3' => [ '--tlsv1.3' ], + }, + 'CURLOPT_SSL_VERIFYPEER' => { '0' => [ '--insecure' ] }, + 'CURLOPT_SSL_VERIFYHOST' => { '0' => [ '--insecure' ] }, + + 'CURLOPT_AWS_SIGV4' => [ '--aws-sigv4', '' ], +); + +sub convert_curlopt_to_cups_parameter { + my ($self, %options) = @_; + + my $key = $options{key}; + + return unless exists $curlopt_to_parameter{$key}; + + # we want an array of parameters + my $parameters = ref $options{parameter} eq 'ARRAY' ? $options{parameter} : [ $options{parameter} ] ; + + my @cups_parameters ; + if (ref $curlopt_to_parameter{$key} eq 'ARRAY') { + @cups_parameters = map { s//$parameters->[0]/; $_ } @{$curlopt_to_parameter{$key}}; + } else { + foreach my $parameter (@$parameters) { + if (exists $curlopt_to_parameter{$key}->{$parameter}) { + push @cups_parameters, @{$curlopt_to_parameter{$key}->{$parameter}}; + } elsif ($parameter =~ /^-/) { + push @cups_parameters, $parameter; + } + } + } + $self->log($_) for @cups_parameters; +} + +1; + +__END__ diff --git a/src/centreon/plugins/http.pm b/src/centreon/plugins/http.pm index 02069bd32..9c9e080b3 100644 --- a/src/centreon/plugins/http.pm +++ b/src/centreon/plugins/http.pm @@ -23,6 +23,8 @@ package centreon::plugins::http; use strict; use warnings; +use centreon::plugins::curllogger; + sub new { my ($class, %options) = @_; my $self = {}; @@ -39,6 +41,8 @@ sub new { $options{options}->add_help(package => __PACKAGE__, sections => 'HTTP GLOBAL OPTIONS'); } + my $curllogger = centreon::plugins::curllogger->new(); + centreon::plugins::misc::mymodule_load( output => $options{output}, module => 'centreon::plugins::backend::http::lwp', @@ -51,7 +55,7 @@ sub new { module => 'centreon::plugins::backend::http::curl', error_msg => "Cannot load module 'centreon::plugins::backend::http::curl'." ); - $self->{backend_curl} = centreon::plugins::backend::http::curl->new(%options); + $self->{backend_curl} = centreon::plugins::backend::http::curl->new(%options, curl_logger => $curllogger); $self->{default_backend} = defined($options{default_backend}) && $options{default_backend} ne '' ? $options{default_backend} : 'lwp'; @@ -260,7 +264,7 @@ Proxy URL. Example: http://my.proxy:3128 =item B<--proxypac> -Proxy pac file (can be a URL or a local file). +Proxy PAC file (can be a URL or a local file). =item B<--insecure> diff --git a/tests/centreon/plugins/curllogger.cookies b/tests/centreon/plugins/curllogger.cookies new file mode 100644 index 000000000..392a37387 --- /dev/null +++ b/tests/centreon/plugins/curllogger.cookies @@ -0,0 +1,5 @@ +# Netscape HTTP Cookie File +# https://curl.se/docs/http-cookies.html +# This file was generated by libcurl! Edit at your own risk. + +.localhost TRUE / FALSE 2121212122 testcookie valeur999 diff --git a/tests/centreon/plugins/curllogger.t b/tests/centreon/plugins/curllogger.t new file mode 100644 index 000000000..769ff981b --- /dev/null +++ b/tests/centreon/plugins/curllogger.t @@ -0,0 +1,272 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Test2::V0; +use Test2::Plugin::NoWarnings echo => 1; + +use Net::Curl::Easy qw(:constants); +use Data::Dumper; +use File::Copy; +use IO::Socket::INET; + +# Here, we test that in various cases, requests made using the centreon +# curl backend and the curl utility send the same headers and data to the +# HTTP server. + +use FindBin; +use lib "$FindBin::RealBin/../../../src"; + +my $port = 7654; +my @output=(); +my $pid; + +{ + package MockOptions; + sub new { bless {}, shift } + sub add_options { } + sub add_help { } +} + +{ + package MockOutput; + + sub new { bless {}, shift } + sub add_option_msg { } + sub output_add { + my ($self, %options) = @_; + + push @output, $options{long_msg}; + + } + sub is_status { } + sub display { } + sub exit { } + sub option_exit { } + sub is_debug { 1 } + sub test_eval { } +} + +use centreon::plugins::http; +use centreon::plugins::misc; + +my $http; + +sub curl_client +{ + my $curlbackend = centreon::plugins::http->new(options=>MockOptions->new(), output=> MockOutput->new(), default_backend => 'curl',); + $curlbackend->set_options(port => $port); + return $curlbackend; +} + +sub test_backend +{ + my (%options) = @_; + + @output=(); + + my $curl = curl_client(); + + if ($options{headers} && ref $options{headers} eq 'ARRAY') { + $curl->add_header(key => $_->{key}, value => $_->{value}) foreach @{$options{headers}} + } + + $curl->request(%options); + # Retrieve headers and data from centreon curl backend output. + my @cupscmd = map { /:\s(.+)$/; $1 } grep { defined && /^curl request.*:/ } @output; + my @sendheader = map { s/^=> Send header: //; s/[\r\n]//g; $_ } grep { defined && /^=> Send header: / } @output; + my @senddata = map { s/^=> Send data: //; s/[\r\n]//g; $_ } grep { defined && /^=> Send data: / } @output; + return { command => @cupscmd == 1 ? $cupscmd[0] : '', + sendheader => @sendheader == 1 ? $sendheader[0] : '', + senddata => @senddata == 1 ? $senddata[0] : '', + }; +} + +sub test_curl +{ + my ($cmd) = @_; + + # Retrieve headers and data from curl output. + # We need to remove the User-Agent header and add the --trace-ascii option, + # otherwise curl does not display the data part. + open my $pipe, '-|', 'sh', '-c', $cmd. ' -H User-Agent: --trace-ascii - 2>&1', or die; + + my $state = 0; + my (@send_header, @send_data); + foreach my $read (<$pipe>) { + if ($read =~ /^=> Send header/) { + $state = 1; + next; + } elsif ($read =~ /^=> Send data/) { + $state = 2; + next; + } elsif ($read =~ /^[=<]/ || $read =~ /^=> R/) { + $state = 0; + next; + } + next unless $read =~ /^0[^:]+:\s(.*)/; + if ($state == 1) { + push @send_header, $1; + } elsif ($state == 2) { + push @send_data, $1; + } + } + + close($pipe); + + return { + sendheader => (join '', @send_header), + senddata => (join '', @send_data) + }; +} + +sub test_full +{ + my ($title, $contains, %options) = @_; + print "test $title\n"; + + my $backend = test_backend(%options); + + # Backend output shoud contain valid curl command + if ($contains && ref $contains eq 'ARRAY') { + my $match = 0; + foreach (@$contains) { + $match++ if $backend->{command} =~ /$_/; + } + ok($match == @$contains, "Command contains required parameters"); + } else { + ok($backend->{command} =~ /^curl/, "Command ok"); + } + + # Backend output should contain a header and/or a data part + ok($backend->{sendheader} || $backend->{senddata}, "Retrieved header/data with backend"); + my $curl = test_curl($backend->{command}); + + # Curl output should contain a header and/or a data part + ok($curl->{sendheader} || $curl->{senddata}, "Retrieved header/data with curl"); + + # We update boundary lines, which normally changes between requests + $backend->{sendheader} =~ s/boundary=----[-a-zA-Z0-9]+/boundary=----XXXXXX/; + $curl->{sendheader}=~ s/boundary=----[-a-zA-Z0-9]+/boundary=----XXXXXX/; + + # We update aws signature lines, which normally changes between requests + $backend->{sendheader} =~ s/(user-agent;)?x-osc-date, Signature=[-a-f0-9]+X-Osc-Date: [\dTZ]+/x-osc-date, Signature=AAAAAAX-Osc-Date: 20250620T140600Z/; + $curl->{sendheader} =~ s/(user-agent;)?x-osc-date, Signature=[-a-f0-9]+X-Osc-Date: [\dTZ]+/x-osc-date, Signature=AAAAAAX-Osc-Date: 20250620T140600Z/; + + $backend->{senddata} =~ s/-------[-a-zA-Z0-9]+/--------XXXXXX/g; + $curl->{senddata}=~ s/-------[-a-zA-Z0-9]+/--------XXXXXX/g; + + # Backend and curl outputs should be the same + ok($backend->{sendheader} eq $curl->{sendheader}, "Headers part match"); + ok($backend->{senddata} eq $curl->{senddata}, "Data part match\n"); +} + +sub setup_env +{ + $pid = fork(); + + # Simulate an HTTP server otherwise curl will not generate any output + if ($pid == 0) { + my $client; + $SIG{'TERM'} = sub { + close($client); + exit(0); + }; + + my $server = IO::Socket::INET->new( LocalHost => '127.0.0.1', + LocalPort => $port, Proto => 'TCP', + Reuse => 1, Listen => 50 ); + + die unless $server; + while (1) { + $client = $server->accept(); + next unless $client; + <$client>; + sleep 1; + close $client if $client; + } + } +} + +setup_env(); + +my $tmpfile = "/tmp/curllogger.cookies"; +copy("$FindBin::RealBin/curllogger.cookies", "$tmpfile"); + +# All requests to be tested +foreach ( { title => "GET with timeout", + options => { full_url => "http://localhost:$port/fake", timeout => 10 } }, + { title => "GET with headers", + options => { full_url => "http://localhost:$port/fake", + headers => [ { key => "header1", value => "valeur 1" }, { key => "header2", value => "valeur 2" } ] } }, + { title => "POST with post_params", + options => { full_url => "http://localhost:$port/fake", method => "POST", + post_params => { "key 1" => "value 1", "key 2" => "value 2" } } }, + { title => "PATCH with timeout", + options => { method => 'PATCH', full_url => "http://localhost:$port/fake", timeout => 10 } }, + { title => "DELETE with timeout", + options => { method => 'DELETE', full_url => "http://localhost:$port/fake", timeout => 10 } }, + { title => "GET with get_params", + options => { full_url => "http://localhost:$port/fake", get_params => [ 'para1', 'valeur1', 'para2', 'valeur2' ] } }, + { title => "GET with no_follow", + options => { full_url => "http://localhost:$port/fake", no_follow => 1 } }, + { title => "GET with cookies_file", + options => { full_url => "http://localhost:$port/fake", cookies_file => $tmpfile }, + contains => [ '--cookie-jar' ] }, + { title => "POST with query_form_post", + options => { full_url => "http://localhost:$port/fake", query_form_post => "une data", + headers => [ { key => "header1", value => "valeur 1" }, { key => "content-type", value => "text/html" } ] } }, + { title => "GET with cert", + options => { full_url => "http://localhost:$port/fake", insecure => 1, cacert_file => '/tmp/ca-fake.crt', + cert_file => '/tmp/cert-fake.crt', key_file => '/tmp/key-fake.pem', cert_pwd => 't@t@' }, + contains => [ '--insecure', '--cert', '--cacert' , '--key', '--pass', ] }, + { title => "GET with pkcs12", + options => { full_url => "http://localhost:$port/fake", cert_pkcs12 => 'P12' }, + contains => [ '--cert-type' ] }, + { title => "GET with proxyurl", + options => { full_url => "http://localhost:$port/fake", proxyurl => "http://localhost:$port" } }, + { title => "GET with authent basic", + options => { full_url => "http://localhost:$port/fake", credentials => 1, basic => 1, username => 'User', + password => 'Pa$$w@rd' }, + contains => [ '--basic' ] }, + { title => "GET with authent ntlmv2", + options => { full_url => "http://localhost:$port/fake", credentials => 1, ntlmv2 => 1, username => 'User', + password => 'Pa$$w@rd' }, + contains => [ '--ntlm' ] }, + { title => "GET with authent digest", + options => { full_url => "http://localhost:$port/fake", credentials => 1, digest => 1, username => 'User', + password => 'Pa$$w@rd' }, + contains => [ '--digest' ] }, + { title => "GET with authent anyauth", + options => { full_url => "http://localhost:$port/fake", credentials => 1, username => 'User', + password => 'Pa$$w@rd' }, + contains => [ '--anyauth' ] }, + { title => "POST with form", + options => { full_url => "http://localhost:$port/fake", method => "POST", + form => [ { copyname => 'part 1', copycontents => 'content 1' }, { copyname => 'part 2', + copycontents => 'content 2' }, ] } }, +) { + test_full($_->{title}, $_->{contains} // '', %{$_->{options}}); +} + +# This test is skipped if the platform does not support CURLOPT_AWS_SIGV4 ( libcurl >= 7.75.0 required ). +SKIP: { + my $test = { title => "GET with curl_opt", + options => { full_url => "http://fake.execute-api.eu-west-1.amazonaws.com:$port/fake", credentials => 1, + username => 'User', http_peer_addr => "127.0.0.1", + password => 'Pa$$w@rd' , curl_opt => [ "CURLOPT_AWS_SIGV4 => osc" ] } }; + + eval "CURLOPT_AWS_SIGV4"; + if ($@) { + print "test ".$test->{title}."\n"; + skip "CURLOPT_AWS_SIGV4 is unsupported on this platform", 5; + } + + test_full($test->{title}, $test->{contains} // '', %{$test->{options}}); +}; + +unlink $tmpfile; + +kill 'TERM', $pid; +waitpid ($pid, 0); + +done_testing(); diff --git a/tests/resources/spellcheck/stopwords.txt b/tests/resources/spellcheck/stopwords.txt index 31f6dabe7..0e02b8fb8 100644 --- a/tests/resources/spellcheck/stopwords.txt +++ b/tests/resources/spellcheck/stopwords.txt @@ -318,6 +318,7 @@ vdomain VDSL2 Veeam VeloCloud +vhost VM VMs VMware