...
 
Commits (13)
......@@ -11,6 +11,9 @@
* [fusioninventory-agent-deployment.vbs](contrib/windows/fusioninventory-agent-deployment.vbs):
FusionInventory Agent deployment helper script
* ADML & ADMX templates to help setup FusionInventory Agent through GPO
* [netdisco_2_glpi.sh](contrib/netdisco/netdisco_2_glpi.sh) by Stoatwblr
This script makes fusioninventory-compatible xml from netdisco data.
Stoatwblr says even if it is ugly and slow, it works ;-)
## Other contribs
......
Revision history for FusionInventory agent
2.5 Fri, 12 Apr 2019
core:
* linux: reload logger during daemonize to avoid issues like not listening http
daemon if logger has still not been used before starting the listener
* Fix #646: HTTP daemon not starting on CentOS 7
* revert dfcb64573e as now more generic fix has been implemented in a538abaed7
(tested on CentOS 6)
* win32: don't show service memory usage on OS not supporting GetProcessMemoryInfo
* Fix #601: Log URL for server target and log path for local target
* win32: add early stderr logging support for service
Just rename "fusioninventory-win32-service.rc.sample" removing ".sample" part
to enable this feature. This can be handy to investigate start service failures.
* Added support for HTTPD plugins
* Added Inventory HTTPD plugins to permit remote inventory request (disabled by default)
* Added Listener target to permit agent to only answer http requests
* Updated configuration to support HTTPD plugins dedicated configuration file
* Added fusioninventory-remoteinventory script to request agent with Inventory
HTTPD plugin enabled
* Fix HTTPD local address reuse
* Added SSL HTTPD plugins to support SSL in any server plugins
* Limit the reload target check to 30 seconds
* win32: report memory usage as Working Set Size (WSS) and Page File Usage (PFU)
* win32: revert handling service with callbacks. Even if Win32::Daemon proposes
the callbacks usage obsoletes the typical skeleton code, the callbacks usage
is known to leak memory and tests with latest Win32::Daemon shows that's true.
* win32: handle task run in a managed thread as this is more efficient than using
perl fork with thread emulation under win32 and preserve a little memory usage.
* win32: wait service control manager is ready before really starting the service
* logger: don't use File::stat module to just get logfile file size, better use -s
as File::stat module seems to fail in rare case.
inventory:
* Bump Inventory task version to 1.7
* Fix lspci command subsystem parsing
* Fix hponcfg.exe can output on stderr on win32 when not really usable
* Skip not working under win32 Generic::Users inventory
Also avoid error in log on /etc/passwd and /etc/group not found files
* Fix #601: Log deviceid as agentid and related target when running an inventory
* Fix #644: Make WORKGROUP inventory consistent
* Fix #541: Don't try to scan virtualbox VM in win32 users directories
* Updated pci.ids to 2019.04.12 version
* Updated usb.ids to 2019.03.20 version
netdiscovery/netinventory:
* Bump NetDiscovery task version to 2.9
* Bump NetInventory task version to 3.3
* Add Lancom in networking devices recognized by description parsing
* Fix #650: discard empty consumable level elements
* Fix #651: discard empty type element
* Add Netdisco export contrib script from Stoatwblr, see contrib/netdisco
* Fix #638: Fix Kyocera counters handling thanks to Stoatwblr
* Printers: assume -2 counter value means a WARNING level and report it
Thanks Stoatwblr for the deep investigation
* Add Oki printer support
* Add APC serialnumber support
* Fix #612: Enhanced Ubnt AccessPoint support
* Updated sysobject.ids (tagged fia-2.5 tag on github repository)
deploy:
* Bump Deploy task version to 2.8
* Fix #394: Check file parts source/mirror url to guaranty it ends with a slash
and trigger an error if it doesn't look like a valid URL.
collect:
* Bump Collect task version to 2.6
* WMI properties can now be a list of properties with comma or space as separator
2.4.3 Fri, 22 Feb 2019
core:
......@@ -32,6 +100,7 @@ inventory:
* Fix #596: Openstack container seen as Physical on win32
* Fix #593: Correct detection of machine type when /var/log/dmesg is too short
* Fix #583: Add BitDefender antivirus support
* Encrypted filesystems support added
* Updated pci.ids to 2019.02.20 version
* Updated usb.ids to 2019.01.17 version
......@@ -45,6 +114,7 @@ netdiscovery/netinventory:
* Add few HP/Compaq serialnumber cases support
* Fix #605: try 'ip neighbor show' if 'arp' is not available for netdiscovery
* Add UPS-MIB support for Riello, S2S & APC
* Components support added
* Updated sysobject.ids (tagged fia-2.4.3 tag on github repository)
2.4.2 Wed, 03 Oct 2018
......@@ -448,6 +518,7 @@ inventory:
* Fixed memory reporting on Solaris
* Enhanced installdate for softwares on many platforms
* Enhanced drive a storage reporting on win32
* Fix #584: Acer B196HQL S/N support
deploy:
* Bump Deploy task version to 2.1.0
......
......@@ -4,12 +4,15 @@ bin/fusioninventory-injector
bin/fusioninventory-inventory
bin/fusioninventory-netdiscovery
bin/fusioninventory-netinventory
bin/fusioninventory-remoteinventory
bin/fusioninventory-wakeonlan
bin/fusioninventory-win32-service
bin/fusioninventory-win32-service.rc.sample
bin/fusioninventory-wmi
Changes
CONTRIB.md
contrib/debian-builder.sh
contrib/netdisco/netdisco_2_glpi.sh
contrib/unix/fusioninventory-agent.init.debian
contrib/unix/fusioninventory-agent.init.redhat
contrib/unix/fusioninventory-agent.service
......@@ -25,6 +28,9 @@ doc/inventory.mdwn
doc/network.mdwn
doc/wakeonlan.mdwn
etc/agent.cfg
etc/inventory-server-plugin.cfg
etc/server-test-plugin.cfg
etc/ssl-server-plugin.cfg
inc/Module/AutoInstall.pm
inc/Module/Install.pm
inc/Module/Install/Base.pm
......@@ -45,6 +51,11 @@ lib/FusionInventory/Agent/HTTP/Client/Fusion.pm
lib/FusionInventory/Agent/HTTP/Client/OCS.pm
lib/FusionInventory/Agent/HTTP/Protocol/https.pm
lib/FusionInventory/Agent/HTTP/Server.pm
lib/FusionInventory/Agent/HTTP/Server/Inventory.pm
lib/FusionInventory/Agent/HTTP/Server/Plugin.pm
lib/FusionInventory/Agent/HTTP/Server/SSL.pm
lib/FusionInventory/Agent/HTTP/Server/Test.pm
lib/FusionInventory/Agent/HTTP/Session.pm
lib/FusionInventory/Agent/Inventory.pm
lib/FusionInventory/Agent/Logger.pm
lib/FusionInventory/Agent/Logger/Backend.pm
......@@ -63,7 +74,9 @@ lib/FusionInventory/Agent/SNMP/MibSupport/HPNetPeripheral.pm
lib/FusionInventory/Agent/SNMP/MibSupport/iLO.pm
lib/FusionInventory/Agent/SNMP/MibSupport/LinuxAppliance.pm
lib/FusionInventory/Agent/SNMP/MibSupport/Mikrotik.pm
lib/FusionInventory/Agent/SNMP/MibSupport/Oki.pm
lib/FusionInventory/Agent/SNMP/MibSupport/Panasas.pm
lib/FusionInventory/Agent/SNMP/MibSupport/Ubnt.pm
lib/FusionInventory/Agent/SNMP/MibSupport/UPS.pm
lib/FusionInventory/Agent/SNMP/MibSupport/Zebra.pm
lib/FusionInventory/Agent/SNMP/MibSupportTemplate.pm
......@@ -72,6 +85,7 @@ lib/FusionInventory/Agent/SOAP/VMware.pm
lib/FusionInventory/Agent/SOAP/VMware/Host.pm
lib/FusionInventory/Agent/Storage.pm
lib/FusionInventory/Agent/Target.pm
lib/FusionInventory/Agent/Target/Listener.pm
lib/FusionInventory/Agent/Target/Local.pm
lib/FusionInventory/Agent/Target/Scheduler.pm
lib/FusionInventory/Agent/Target/Server.pm
......@@ -365,9 +379,6 @@ lib/FusionInventory/Agent/XML/Query/Prolog.pm
lib/FusionInventory/Agent/XML/Response.pm
lib/setup.pm
LICENSE
list-m.txt
list-t.txt
list.txt
Makefile.PL
MANIFEST This list of files
META.yml
......@@ -697,6 +708,7 @@ resources/generic/edid/lcd.acer-al19161.3
resources/generic/edid/lcd.acer-al19161.4
resources/generic/edid/lcd.acer-al1921
resources/generic/edid/lcd.acer-asp1680
resources/generic/edid/lcd.acer-b196hql
resources/generic/edid/lcd.acer-b226hql
resources/generic/edid/lcd.acer-b226hql.28.2016
resources/generic/edid/lcd.acer-b243h
......
......@@ -40,7 +40,7 @@ no_index:
provides:
FusionInventory::Agent:
file: lib/FusionInventory/Agent.pm
version: 2.4.3
version: '2.5'
recommends:
Archive::Extract: 0
Compress::Zlib: 0
......@@ -75,4 +75,4 @@ resources:
homepage: http://www.fusioninventory.org
license: http://opensource.org/licenses/gpl-license.php
repository: https://github.com/fusioninventory/fusioninventory-agent/
version: 2.4.3
version: '2.5'
......@@ -241,14 +241,17 @@ sub install {
config_install : pure_install
$(MKPATH) $(DESTDIR)$(SYSCONFDIR)
$(NOECHO) $(CHMOD) $(PERM_DIR) $(DESTDIR)$(SYSCONFDIR)
if $(TEST_F) $(DESTDIR)/$(SYSCONFDIR)/agent.cfg; then \
$(RM_F) $(DESTDIR)$(SYSCONFDIR)/agent.cfg.new; \
$(CP) etc/agent.cfg $(DESTDIR)$(SYSCONFDIR)/agent.cfg.new; \
$(CHMOD) $(PERM_RW) $(DESTDIR)$(SYSCONFDIR)/agent.cfg.new; \
else \
$(CP) etc/agent.cfg $(DESTDIR)$(SYSCONFDIR)/agent.cfg; \
$(CHMOD) $(PERM_RW) $(DESTDIR)$(SYSCONFDIR)/agent.cfg; \
fi
for config in agent.cfg inventory-server-plugin.cfg server-test-plugin.cfg ssl-server-plugin.cfg ; \
do \
if $(TEST_F) $(DESTDIR)/$(SYSCONFDIR)/$$config; then \
$(RM_F) $(DESTDIR)$(SYSCONFDIR)/$$config.new; \
$(CP) etc/agent.cfg $(DESTDIR)$(SYSCONFDIR)/$$config.new; \
$(CHMOD) $(PERM_RW) $(DESTDIR)$(SYSCONFDIR)/$$config.new; \
else \
$(CP) etc/agent.cfg $(DESTDIR)$(SYSCONFDIR)/$$config; \
$(CHMOD) $(PERM_RW) $(DESTDIR)$(SYSCONFDIR)/$$config; \
fi; \
done
$(ABSPERLRUN) -pi \
-e "s|=> undef, # SYSCONFDIR.*|=> '$(SYSCONFDIR)',|;" \
$(DESTDIR)$(DATADIR)/lib/FusionInventory/Agent/Config.pm
......
......@@ -52,6 +52,7 @@ GetOptions(
'httpd-ip=s',
'httpd-port=s',
'httpd-trust=s',
'listen',
'scan-homedirs',
'scan-profiles',
'server|s=s',
......@@ -219,6 +220,8 @@ fusioninventory-agent [options] [--server server|--local path]
--httpd-port=PORT network port to listen to (62354)
--httpd-trust=IP trust requests without authentication
token (false)
--listen enable listener target if no local or
server target is defined
Logging options:
--logger=BACKEND logger backend (stderr)
......@@ -275,15 +278,15 @@ Send the results of tasks execution to given server.
If I<URI> doesn't start with http:// or https://, the agent assume the
parameter is a hostname and rewrite it as:
% --server=http://servername/ocsinventory
% --server=http://example/plugins/fusioninventory
In general, OCS Inventory server URL have this format:
http://servername/ocsinventory
http://example/ocsinventory
and FusionInventory for GLPI this one:
http://servername/glpi/plugins/fusioninventory/front/plugin_fusioninventory.communication.php
http://example/glpi/plugins/fusioninventory/front/plugin_fusioninventory.communication.php
Multiple values can be specified, using comma as a separator.
......@@ -535,6 +538,12 @@ documentation to get more example.
Multiple values can be specified, using comma as a separator.
=item B<--listen>
This option should be used if no local or server target is defined and
the agent still needs to answer http requests. B<--no-httpd> should not be set
and B<--httpd-trust> should be set to enable trusted remote clients.
=back
=head2 Logging options
......
......@@ -108,7 +108,7 @@ fusioninventory-esx --host <host> --user <user> --password <password> --director
You can import the .ocs file in your inventory server with the fusioninventory-injector tool.
%fusioninventory-injector -v --file /tmp/*.ocs -u https://myserver/plugins/fusioninventory/
%fusioninventory-injector -v --file /tmp/*.ocs -u https://example/plugins/fusioninventory/
=head1 DESCRIPTION
......
......@@ -178,8 +178,8 @@ fusioninventory-injector [options] [--file <file>|--directory <directory>|--stdi
-C --no-compression don't compress sent XML inventories
Examples:
fusioninventory-injector -v -f /tmp/toto-2010-09-10-11-42-22.ocs --url https://login:pw@server/plugins/fusioninventory/
fusioninventory-injector -v -R -d /srv/ftp/fusion --url https://login:pw@glpi-server/plugins/fusioninventory/
fusioninventory-injector -v -f /tmp/toto-2010-09-10-11-42-22.ocs --url https://login:pw@example/plugins/fusioninventory/
fusioninventory-injector -v -R -d /srv/ftp/fusion --url https://login:pw@example/plugins/fusioninventory/
=head1 DESCRIPTION
......
......@@ -247,7 +247,7 @@ Possible values are: udp/ipv4,udp/ipv6,tcp/ipv4,tcp/ipv6
=item B<--file> I<FILE>
Run an offline inventory against snmpwalk output, stored in given file.
Run an offline inventory against snmpwalk output, stored in given file.
Multiple usage allowed, for multiple files.
=item B<--communty> I<STRING>
......
#!/usr/bin/perl
use strict;
use warnings;
use UNIVERSAL::require;
use English qw(-no_match_vars);
use LWP::UserAgent;
use Pod::Usage;
use Getopt::Long;
use Digest::SHA;
use XML::TreePP;
use Time::HiRes qw(gettimeofday);
use File::Which;
our $VERSION = "1.0";
my $options = {
useragent => "FusionInventory-RemoveInventory/$VERSION",
};
GetOptions(
$options,
'help|h',
'useragent|u=s',
'verbose|v',
'debug',
'port|p=i',
'timeout|t=i',
'baseurl|b=s',
'token|T=s',
'directory|d=s',
'id=s',
'ssl|s',
'ca-cert-file=s',
'no-ssl-check',
'no-compression|C',
) or pod2usage(-verbose => 0);
pod2usage(-verbose => 0, -exitstatus => 0) if $options->{help};
pod2usage(
-message => "\nGive a least one host to get inventory from as parameter\n",
-verbose => 0,
-exitstatus => 1
) unless @ARGV;
pod2usage(
-message => "\nNo token as shared secret defined\n",
-verbose => 0,
-exitstatus => 1
) unless $options->{token};
pod2usage(
-message => "\nWhen asking inventory to more than one host, you must use the --directory parameter\n",
-verbose => 0,
-exitstatus => 1
) if !$options->{directory} && @ARGV>1;
pod2usage(
-message => "\nDirectory not found: $options->{directory}\n",
-verbose => 0,
-exitstatus => 1
) if ($options->{directory} && ! -d $options->{directory});
my $ua = LWP::UserAgent->new(
agent => $options->{useragent},
timeout => $options->{timeout} || 180,
parse_head => 0, # No need to parse HTML
keep_alive => 1,
);
if ($options->{ssl}) {
$ua->ssl_opts(SSL_ca_file => $options->{'ca-cert-file'})
if $options->{'ca-cert-file'};
$ua->ssl_opts(verify_hostname => 0, SSL_verify_mode => 0)
if $options->{ssl} && $options->{'no-ssl-check'};
}
$options->{verbose} = 1 if $options->{debug};
my $id = $options->{id} || id();
warn "Using $id as request id\n"
if $options->{verbose};
foreach my $host (@ARGV) {
my $url = ( $options->{ssl} ? "https://" : "http://" ). $host;
$url .= $options->{port} ? ":".$options->{port} : ":62354";
$url .= $options->{baseurl} ? $options->{baseurl} : "/inventory";
warn "$host: Trying $url\n"
if $options->{verbose};
my $req = HTTP::Request->new(GET => $url.'/session');
$req->header( 'X-Request-ID' => $id );
$req->protocol( 'HTTP/1.1' );
if ($options->{debug}) {
warn "--->\n";
warn "Request: ".$req->as_string();
}
my $session = $ua->request($req);
if ($options->{debug}) {
warn "<---\n";
warn "Response: ".$session->as_string();
}
if (!$session->is_success()) {
warn "$host: No session (".$session->status_line().")\n";
next;
}
my $nonce = $session->header('X-Auth-Nonce')
or die "No nonce\n";
my $sha = Digest::SHA->new(256);
$sha->add($nonce.'++'.$options->{token});
my $payload = $sha->b64digest;
# Update request to get inventory
$req->uri($url.'/get');
$req->header( 'X-Auth-Payload' => $payload );
# Set Accept header
my $accept = 'application/xml';
if (!$options->{'no-compression'}) {
$accept .= ', application/x-compress-zlib'
if Compress::Zlib->require();
my $zcat = scalar(which('zcat'));
$accept .= ', application/x-compress-gzip'
if -x $zcat;
}
$req->header('Accept' => $accept);
if ($options->{debug}) {
warn "--->\n";
warn "Request: ".$req->as_string();
}
my $xml = $ua->request($req);
if ($options->{debug}) {
warn "<---\n";
warn "Response: ".$xml->status_line()."\n".$xml->headers->as_string()."\n";
}
if (!$xml->is_success()) {
warn "$host: Inventory request: ".$xml->status_line()."\n";
next;
}
my $content = $xml->content();
# check compression mode
if ($xml->header('Content-Type') eq 'application/x-compress-zlib') {
# RFC 1950
warn "$host: Using Compress::Zlib for decompression\n"
if $options->{debug};
$content = Compress::Zlib::uncompress($content);
} elsif ($xml->header('Content-Type') eq 'application/x-compress-gzip') {
# RFC 1952
warn "$host: Using gzip for decompression\n"
if $options->{debug};
File::Temp->require();
my $fd = File::Temp->new();
print $fd $content;
close $fd;
unless(open OUT, 'zcat ' . $fd->filename() . '|') {
warn "$host: Failed to uncompress response, skipping\n";
next;
}
local $INPUT_RECORD_SEPARATOR; # Set input to "slurp" mode.
$content = <OUT>;
close(OUT);
}
my $deviceid;
eval {
my $tpp = XML::TreePP->new();
my $tree = $tpp->parse($content);
$deviceid = $tree->{REQUEST}->{DEVICEID};
};
unless ($deviceid) {
warn "$host: No deviceid found in returned inventory output, skipping\n";
next;
}
warn "$host: Got remote inventory from $deviceid\n"
if $options->{verbose};
if ($options->{directory}) {
my $filename = $options->{directory}."/$deviceid.xml";
open FILE, ">", $filename
or die "$host: Can't open $filename: $!\n";
print FILE $content;
close(FILE);
warn "$host: Written inventory in $filename\n"
if $options->{verbose};
} else {
print $content;
}
}
exit(0);
# Compute a simple and as-possible safe id
sub id {
my $sha = Digest::SHA->new(1);
$sha->add(gettimeofday());
$sha->add(gettimeofday());
my $digest = $sha->hexdigest;
return substr($digest, 0, 8);
}
__END__
=head1 NAME
fusioninventory-remoteinventory - A tool to pull inventory from an agent
=head1 SYNOPSIS
fusioninventory-remoteinventory [options] <host1> [<host2> ...]
Options:
-h --help this menu
-d --directory load every .ocs files from a directory
-t --timeout requests timeout and even inventory get timeout
-b --baseurl remote base url if not /inventory
-p --port remote port (62354 by default)
-T --token token as shared secret
-i --id id for request to identify requests in agent log
-s --ssl connect using SSL
--no-ssl-check do not check agent SSL certificate
--ca-cert-file CA certificates file
-C --no-compression
ask to not compress sent XML inventories
-v --verbose verbose mode
--debug debug mode
-u --useragent set used HTTP User-Agent for requests
Examples:
fusioninventory-remoteinventory -T strong-shared-secret 192.168.43.236
fusioninventory-remoteinventory -v -T strong-shared-secret 192.168.43.237 | \
fusioninventory-injector -url https://login:pw@server/plugins/fusioninventory/
fusioninventory-remoteinventory -T strong-shared-secret -d /tmp 192.168.43.236 192.168.43.237
=head1 DESCRIPTION
This tool can be used to securely request an inventory from remote agents not able
to contact a server.
......@@ -13,6 +13,10 @@ use Pod::Usage;
use FusionInventory::Agent::Daemon::Win32;
# Load dedicated .rc file if present. Sample one, if renamed, permits
# to log stdout and stderr for early debugging purpose
do __FILE__ . ".rc" if (!@ARGV && -e __FILE__ . ".rc");
Getopt::Long::Configure( "no_ignorecase" );
my %options = ();
......@@ -59,9 +63,6 @@ if ($options{register}) {
# we need to do it by ourself
chdir($directory);
# Register default callbacks
$service->RegisterCallbacks();
# Under newer win32 releases, setting accepted controls may be required
$service->AcceptedControls();
......
BEGIN {
use File::Spec;
my $logdir = File::Spec->rel2abs( '../../../logs', __FILE__ );
#~ $logdir = "c:/temp";
if (-d $logdir) {
open(STDERR, ">$logdir/stderr.txt")
or die "Can't redirect STDERR to stderr.txt: $!";
open(STDOUT, ">$logdir/stdout.txt")
or die "Can't redirect STDOUT to stdout.txt: $!";
select STDERR;
$| = 1;
select STDOUT;
$| = 1;
print STDERR localtime().": BEGIN stderr.txt\n";
print localtime().": BEGIN stdout.txt\n";
} else {
print STDERR localtime().": Logging folder $logdir is missing\n";
}
}
END {
print STDERR localtime().": END stderr.txt\n";
print localtime().": END stdout.txt\n";
}
This diff is collapsed.
fusioninventory-agent (1:2.5-1) unstable; urgency=low
FusionInventory agent httpd server now supports plugins.
Available plugins are:
- Inventory: authorizes to remotely and securely request an inventory when enabled
- SSL: use it to enable SSL support for any other plugin, even on default port
- Test: just a sample plugin
All agent httpd server plugins are disabled by default and can be enabled using
any of the associated configuration available in /etc/fusioninventory: to enable
a plugin, just copy the associated default conf renaming it with .local extension
in place of .cfg and set "disabled" option to "no". Don't miss any other mandatory
option.
Configuration parameters are described in configurations.
A new script fusioninventory-remoteinventory is also installed and can be used
to request an inventory from an agent with httpd server Inventory plugin enabled.
-- Guillaume Bougard <gbougard@teclib.com> Sat, 13 Apr 2019 14:20:58 +0200
fusioninventory-agent (1:2.4.1-1) unstable; urgency=low
Nmap is no more used by FusionInventory NetDiscovery task, you can safely
......
fusioninventory-agent (1:2.4.3-1) UNRELEASED; urgency=medium
fusioninventory-agent (1:2.5-1) UNRELEASED; urgency=low
NOTES:
- wait for buster release with this new upstream version
* New upstream version 2.5
* Remove avoid-syslog-logger-error-on-debian patch as fixed upstream
* Install default fusioninventory-agent httpd server new plugin configurations
* Add NEWS entry for the new agent httpd server plugin system
* Add diverted new configuration files in d/not-installed
* Add patch to fix deviceid for fusioninventory-inventory script
* Add patch to also install fusioiinventory-remoteinventory script
-- Guillaume Bougard <gbougard@teclib.com> Sat, 13 Apr 2019 14:20:58 +0200
fusioninventory-agent (1:2.4.3-1) unstable; urgency=medium
* New upstream version 2.4.3
* Add fusioninventory-agent-task-network dependency to support
SNMPv3 authentication
......
......@@ -7,8 +7,11 @@ case "$1" in
configure)
[ -d "/etc/fusioninventory" ] || mkdir "/etc/fusioninventory"
[ -d "/etc/fusioninventory/conf.d" ] || mkdir "/etc/fusioninventory/conf.d"
ucf /usr/share/fusioninventory/etc/agent.cfg /etc/fusioninventory/agent.cfg
ucfr fusioninventory-agent /etc/fusioninventory/agent.cfg
for conf in agent inventory-server-plugin ssl-server-plugin server-test-plugin
do
ucf /usr/share/fusioninventory/etc/$conf.cfg /etc/fusioninventory/$conf.cfg
ucfr fusioninventory-agent /etc/fusioninventory/$conf.cfg
done
;;
esac
......
......@@ -6,22 +6,34 @@ set -e
case "$1" in
purge)
for ext in '~' '%' .bak .ucf-new .ucf-old .ucf-dist; do
rm -f /etc/fusioninventory/agent.cfg$ext
for conf in agent inventory-server-plugin ssl-server-plugin server-test-plugin
do
rm -f /etc/fusioninventory/$conf.cfg$ext
done
done
# Cleanup var dir
rm -rf /var/lib/fusioninventory-agent
# remove the configuration file itself
rm -f /etc/fusioninventory/agent.cfg
for conf in agent inventory-server-plugin ssl-server-plugin server-test-plugin
do
rm -f /etc/fusioninventory/$conf.cfg
done
[ -d /etc/fusioninventory ] && rmdir --ignore-fail-on-non-empty /etc/fusioninventory
# and finally clear it out from the ucf database
if which ucf >/dev/null; then
ucf --purge /etc/fusioninventory/agent.cfg
for conf in agent inventory-server-plugin ssl-server-plugin server-test-plugin
do
ucf --purge /etc/fusioninventory/$conf.conf
done
fi
if which ucfr >/dev/null; then
ucfr --purge fusioninventory-agent /etc/fusioninventory/agent.cfg
for conf in agent inventory-server-plugin ssl-server-plugin server-test-plugin
do
ucfr --purge fusioninventory-agent /etc/fusioninventory/$conf.cfg
done
fi
;;
......
# Diverted from /usr/share/fusioninventory/etc during postinst
/etc/fusioninventory/agent.cfg
/etc/fusioninventory/inventory-server-plugin.cfg
/etc/fusioninventory/server-test-plugin.cfg
/etc/fusioninventory/ssl-server-plugin.cfg
# Files provided by hwdata package
/usr/share/fusioninventory/pci.ids
......
Description: Remove a test failing in debian
The Sys::Syslog module version in debian may not be numeric.
Just remove the test as module should be recent enough in debian.
Author: Guillaume Bougard <gbougard@teclib.com>
Last-Update: 2019--03-06
--- fusioninventory-agent-2.4.3.orig/lib/FusionInventory/Agent/Logger/Syslog.pm
+++ fusioninventory-agent-2.4.3/lib/FusionInventory/Agent/Logger/Syslog.pm
@@ -27,10 +27,6 @@ sub new {
openlog($syslog_name, 'cons,pid', $params{logfacility} || 'LOG_USER');
- # Fix agent not listening on http port issue when 'syslog' logger is
- # active and Sys::Syslog is too old. Problem seen on CentOS 6.10
- Sys::Syslog::setlogsock('unix') if $Sys::Syslog::VERSION < 0.28 ;
-
return $self;
}
Description: Fix deviceid for inventory script
fusioninventory-inventory script doesn't create a deviceid by default. In that
case a log message just fails. This patch just fixes the log message to take
the inventory deviceid to avoid the error.
Author: Guillaume Bougard <gbougard@teclib.com>
Last-Update: 2019-04-13
--- fusioninventory-agent-2.5.orig/lib/FusionInventory/Agent/Task/Inventory.pm
+++ fusioninventory-agent-2.5/lib/FusionInventory/Agent/Task/Inventory.pm
@@ -59,7 +59,7 @@ sub run {
tag => $tag
);
- $self->{logger}->info("New inventory from $self->{deviceid} for $self->{target}->{id}".
+ $self->{logger}->info("New inventory from ".$inventory->getDeviceId()." for $self->{target}->{id}".
( (defined($tag) && length($tag)) ? " (tag=$tag)" : "" ));
# Set inventory as remote if running remote inventory like from wmi task
Description: Install fusioninventory-remoteinventory script
Update Makefile.PL to also install fusioninventory-remoteinventory script
Author: Guillaume Bougard <gbougard@teclib.com>
Last-Update: 2019-04-13
--- fusioninventory-agent-2.5.orig/Makefile.PL
+++ fusioninventory-agent-2.5/Makefile.PL
@@ -104,6 +104,7 @@ install_script 'bin/fusioninventory-wake
install_script 'bin/fusioninventory-netdiscovery';
install_script 'bin/fusioninventory-netinventory';
install_script 'bin/fusioninventory-esx';
+install_script 'bin/fusioninventory-remoteinventory';
resources
homepage => "http://www.fusioninventory.org",
default_config.patch
simpler-setup-module.patch
skip-rpm-parsing-test.patch
avoid-syslog-logger-error-on-debian
fix-deviceid-for-inventory-script
install-remoteinventory-script
......@@ -40,6 +40,9 @@ sub wanted {
};
print AGENT "etc/agent.cfg /usr/share/fusioninventory/etc\n";
print AGENT "etc/inventory-server-plugin.cfg /usr/share/fusioninventory/etc\n";
print AGENT "etc/ssl-server-plugin.cfg /usr/share/fusioninventory/etc\n";
print AGENT "etc/server-test-plugin.cfg /usr/share/fusioninventory/etc\n";
print AGENT "usr/share/fusioninventory/edid.ids\n";
print AGENT "usr/share/fusioninventory/sysobject.ids\n";
print AGENT "usr/share/fusioninventory/html\n";
......
# Set this to no or 0 to enable Inventory HTTP::Daemon Server plugin and
# permit remote inventory request for this agent
disabled = yes
# Set base url matching for API
#url_match = /inventory
# Port on which to listen for inventory requests, default to legacy port
#port = 62354
# token as private secret used to verify authorization token, not defined by
# default, but mandatory to access API
#token = [secret-string]
# A timeout for session to no more trust a client payload
#session_timeout = 60
# Set this to 'yes' if XML compression is not not required
#no_compress = no
# To limit any abuse we expect a maximum of 50 requests by hour (3600 seconds)
# You can adjust the rate limitation by updating the requests number limit
# or the period on which apply the requests number limit
#maxrate = 50
#maxrate_period = 3600
# You should create and define you specific parameter in the following
# included configuration file to override any default.
# For example just set "disabled = no" in it to enable the plugin
include "inventory-server-plugin.local"
disabled = yes
#configtest = test
#port = 62355
# You should create and define you specific parameter in the following
# included configuration file to override any default.
# For example just set "disabled = no" in it to enable the plugin
include "server-test-plugin.local"
disabled = yes
# Comma separated list of ports like in: ports = 62355,62356
#ports = 0
# Example command to generate key/certificate files pair
# openssl req -x509 -newkey rsa:2048 -keyout etc/key.pem -out etc/cert.pem -days 3650 -sha256 -nodes -subj "/CN=127.0.0.1"
#ssl_cert_file = cert.pem
#ssl_key_file = key.pem
# You should create and define you specific parameter in the following
# included configuration file to override any default.
# For example just set "disabled = no" in it to enable the plugin
include "ssl-server-plugin.local"
......@@ -104,13 +104,17 @@ sub init {
}
foreach my $target ($self->getTargets()) {
$logger->debug($target->getType() . " target: " . $target->getName());
if ($target->isType('local') || $target->isType('server')) {
$logger->debug("target $target->{id}: " . $target->getType() . " " . $target->getName());
} else {
$logger->debug("target $target->{id}: " . $target->getType());
}
# Register planned tasks by target
my @planned = $target->plannedTasks(@plannedTasks);
if (@planned) {
$logger->debug("Planned tasks:");
$logger->debug("Planned tasks for $target->{id}:");
foreach my $task (@planned) {
my $task_lc = lc $task;
$logger->debug("- $task: " . $available{$available_lc{$task_lc}});
......@@ -181,6 +185,10 @@ sub terminate {
sub runTarget {
my ($self, $target) = @_;
if ($target->isType('local') || $target->isType('server')) {
$self->{logger}->info("target $target->{id}: " . $target->getType() . " " . $target->getName());
}
# the prolog dialog must be done once for all tasks,
# but only for server targets
my $response;
......@@ -206,7 +214,7 @@ sub runTarget {
deviceid => $self->{deviceid},
);
$self->{logger}->info("sending prolog request to server $target->{id}");
$self->{logger}->info("sending prolog request to $target->{id}");
$response = $client->send(
url => $target->getUrl(),
message => $prolog
......
......@@ -41,6 +41,7 @@ my $default = {
'httpd-ip' => undef,
'httpd-port' => 62354,
'httpd-trust' => [],
'listen' => undef,
'scan-homedirs' => undef,
'scan-profiles' => undef,
'server' => undef,
......@@ -103,7 +104,7 @@ sub _loadFromBackend {
SWITCH: {
if ($backend eq 'registry') {
die "Unavailable configuration backend\n"
die "Config: Unavailable configuration backend\n"
unless $OSNAME eq 'MSWin32';
$self->_loadFromRegistry();
last SWITCH;
......@@ -112,7 +113,7 @@ sub _loadFromBackend {
if ($backend eq 'file') {
# Handle loadedConfs to avoid loops
$self->{loadedConfs} = {};
$self->_loadFromFile({
$self->loadFromFile({
file => $confFile
});
delete $self->{loadedConfs};
......@@ -123,7 +124,7 @@ sub _loadFromBackend {
last SWITCH;
}
die "Unknown configuration backend '$backend'\n";
die "Config: Unknown configuration backend '$backend'\n";
}
}
......@@ -157,7 +158,7 @@ sub _loadFromRegistry {
my $machKey = $Registry->Open('LMachine', {
Access => Win32::TieRegistry::KEY_READ()
}) or die "Can't open HKEY_LOCAL_MACHINE key: $EXTENDED_OS_ERROR";
}) or die "Config: Can't open HKEY_LOCAL_MACHINE key: $EXTENDED_OS_ERROR\n";
my $provider = $FusionInventory::Agent::Version::PROVIDER;
my $settings = $machKey->{"SOFTWARE/$provider-Agent"};
......@@ -174,7 +175,7 @@ sub _loadFromRegistry {
if (exists $default->{$key}) {
$self->{$key} = $val;
} else {
warn "unknown configuration directive $key";
warn "Config: unknown configuration directive $key\n";
}
}
}
......@@ -185,21 +186,21 @@ sub confdir {
return $self->{_confdir};
}
sub _loadFromFile {
sub loadFromFile {
my ($self, $params) = @_;
my $file = $params->{file} ?
$params->{file} : $self->{_confdir} . '/agent.cfg';
if ($file) {
die "non-existing file $file" unless -f $file;
die "non-readable file $file" unless -r $file;
die "Config: non-existing file $file\n" unless -f $file;
die "Config: non-readable file $file\n" unless -r $file;
} else {
die "no configuration file";
die "Config: no configuration file\n";
}
# Don't reload conf if still loaded avoiding loops due to include directive
if ($self->{loadedConfs}->{$file}) {
warn "$file configuration file still loaded\n"
warn "Config: $file configuration file still loaded\n"
if $self->{logger} && ucfirst($self->{logger}) eq 'Stderr';
return;
}
......@@ -207,7 +208,7 @@ sub _loadFromFile {
my $handle;
if (!open $handle, '<', $file) {
warn "Config: Failed to open $file: $ERRNO";
warn "Config: Failed to open $file: $ERRNO\n";
return;
}
......@@ -223,39 +224,41 @@ sub _loadFromFile {
if ($val =~ /^(['"])([^\1]*)\1/) {
my ($quote, $extract) = ( $1, $2 );
$val =~ s/\s*#.+$//;
warn "We may have been confused for $key quoted value, our extracted value: '$extract'"
warn "Config: We may have been confused for $key quoted value, our extracted value: '$extract'\n"
if ($val ne "$quote$extract$quote");
$val = $extract ;
} else {
$val =~ s/\s*#.+$//;
}
if (exists $default->{$key}) {
if ($params->{defaults} && exists $params->{defaults}->{$key}) {
$self->{$key} = $val;
} elsif (!$params->{defaults} && exists $default->{$key}) {
$self->{$key} = $val;
} elsif (lc($key) eq 'include') {
$self->_includeDirective($val, $file);
} else {
warn "unknown configuration directive $key";
warn "Config: unknown configuration directive $key\n";
}
} elsif ($line =~ /^\s*include\s+(.+)$/i) {
my $include = $1;
if ($include =~ /^(['"])([^\1]*)\1/) {
my ($quote, $extract) = ( $1, $2 );
$include =~ s/\s*#.+$//;
warn "We may have been confused for include quoted path, our extracted path: '$extract'"
warn "Config: We may have been confused for include quoted path, our extracted path: '$extract'\n"
if ($include ne "$quote$extract$quote");
$include = $extract ;
} else {
$include =~ s/\s*#.+$//;
}
$self->_includeDirective($include, $file);
$self->_includeDirective($include, $file, $params->{defaults});
}
}
close $handle;
}
sub _includeDirective {
my ($self, $include, $currentconfig) = @_;
my ($self, $include, $currentconfig, $defaults) = @_;
# Make include path absolute, relatively to current file basedir
unless (File::Spec->file_name_is_absolute($include)) {
......@@ -273,10 +276,10 @@ sub _includeDirective {
foreach my $cfg ( sort glob("$include/*.cfg") ) {
# Skip missing or non-readable file
next unless -f $cfg && -r $cfg;
$self->_loadFromFile({ file => $cfg });
$self->loadFromFile({ file => $cfg, defaults => $defaults });
}
} elsif ( -f $include && -r $include ) {
$self->_loadFromFile({ file => $include });
$self->loadFromFile({ file => $include, defaults => $defaults });
}
}
......@@ -300,7 +303,7 @@ sub _checkContent {
my $handler = $deprecated->{$old};
# notify user of deprecation
warn "the '$old' option is deprecated, $handler->{message}\n";
warn "Config: the '$old' option is deprecated, $handler->{message}\n";
# transfer the value to the new option, if possible
if ($handler->{new}) {
......@@ -339,12 +342,12 @@ sub _checkContent {
# ca-cert-file and ca-cert-dir are antagonists
if ($self->{'ca-cert-file'} && $self->{'ca-cert-dir'}) {
die "use either 'ca-cert-file' or 'ca-cert-dir' option, not both\n";
die "Config: use either 'ca-cert-file' or 'ca-cert-dir' option, not both\n";
}
# logger backend without a logfile isn't enoguh
if ($self->{'logger'} =~ /file/i && ! $self->{'logfile'}) {
die "usage of 'file' logger backend makes 'logfile' option mandatory\n";
die "Config: usage of 'file' logger backend makes 'logfile' option mandatory\n";
}
# multi-values options, the default separator is a ','
......@@ -456,6 +459,18 @@ sub getTargets {
}
}
# Only add listener target if no other target has been defined and
# httpd daemon is enabled. And anyway only one listener should be enabled
if ($self->{listen} && !@targets && !$self->{'no-httpd'}) {
FusionInventory::Agent::Target::Listener->require();
push @targets,
FusionInventory::Agent::Target::Listener->new(
logger => $params{logger},
delaytime => $self->{delaytime},
basevardir => $params{vardir},
);
}
return \@targets;
}
......
......@@ -279,6 +279,9 @@ sub createDaemon {
} elsif (my $pid = $daemon->Init()) {
$logger->debug("$PROVIDER Agent daemonized with PID $pid") if $logger;
exit 0;
} else {
# Reload the logger in forked process to avoid some related issues
$logger->reload();
}
# From here we can enable our pidfile deletion on terminate
......
This diff is collapsed.
This diff is collapsed.
package FusionInventory::Agent::HTTP::Server::Inventory;
use strict;
use warnings;
use English qw(-no_match_vars);
use base "FusionInventory::Agent::HTTP::Server::Plugin";
use FusionInventory::Agent::Tools;
use FusionInventory::Agent::Task::Inventory;
use FusionInventory::Agent::Target::Listener;
our $VERSION = "1.1";
sub urlMatch {
my ($self, $path) = @_;
# By default, re_path_match => qr{^/inventory/(session|get|apiversion)$}
return 0 unless $path =~ $self->{re_path_match};
$self->{request} = $1;
return 1;
}
sub log_prefix {
return "[inventory server plugin] ";
}
sub config_file {
return "inventory-server-plugin.cfg";
}
sub defaults {
return {
disabled => "yes",
url_path => "/inventory",
port => 0,
token => undef,
session_timeout => 60,
no_compress => "no",
# Supported by class FusionInventory::Agent::HTTP::Server::Plugin
maxrate => 30,
maxrate_period => 3600,
};
}
sub init {
my ($self) = @_;
$self->SUPER::init(@_);
$self->{request} = 'none';
my $defaults = $self->defaults();
my $url_path = $self->config('url_path');
$self->debug("Using $url_path as base url matching")
if ($url_path ne $defaults->{url_path});
$self->{re_path_match} = qr{^$url_path/(session|get|apiversion)$};
# Always uses a dedicated Listener target for this plugin. It will give access
# to stored sessions
$self->{target} = FusionInventory::Agent::Target::Listener->new(
logger => $self->{logger},
basevardir => $self->{server}->{agent}->{config}->{vardir},
);
# Check secret is set if plugin is enabled
if (!$self->disabled() && !$self->config('token')) {
$self->error("Plugin enabled without token in configuration");
$self->disable();
$self->info("Plugin disabled on wrong configuration");
}
# Normalize no_compress
$self->{no_compress} = $self->config('no_compress') !~ /^0|no$/i ? 1 : 0;
}
sub handle {
my ($self, $client, $request, $clientIp) = @_;
my $logger = $self->{logger};
my $target = $self->{target};
# rate limit by ip to avoid abuse
if ($self->rate_limited($clientIp)) {
$client->send_error(429); # Too Many Requests
return 429;
}
if ($self->{request} eq 'apiversion') {
my $response = HTTP::Response->new(
200,
'OK',
HTTP::Headers->new( 'Content-Type' => 'text/plain' ),
$VERSION
);
$client->send_response($response);
return 200;
}
my $id = $request->header('X-Request-ID');
unless ($id) {
$self->info("No mandatory X-Request-ID header provided in $self->{request} request from $clientIp");
$client->send_error(403, 'No session available');
return 403;
}
my $remoteid = "{$id}\@[$clientIp]";
my $session = $target->session(
remoteid => $remoteid,
timeout => $self->config('session_timeout'),
);
unless ($session) {
$self->info("No session available for $remoteid");
$client->send_error(403, 'No session available');
return 403;
}
if ($self->{request} eq 'session') {
my $nonce = $session->nonce();
unless ($nonce) {
$self->info("Session setup failure for $remoteid");
$client->send_error(500, 'Session failure');
return 500;
}
# Returned content is not useful but it should not be empty to support keep-alive
# This is a LWP::UserAgent limitation
my $response = HTTP::Response->new(
200,
'OK',
HTTP::Headers->new( 'X-Auth-Nonce' => $nonce, 'Content-Type' => 'Plain/Text' ),
"waiting inventory request..."
);
$client->send_response($response);
# Expect another client request if possible
$self->{keepalive} = 1
if $request->header('Keep-Alive');
return 200;
}
my $authorization = $session->authorized(
token => $self->config('token'),
payload => $request->header('X-Auth-Payload') || ''
);
# Still cleanup the session
$target->clean_session($remoteid);
unless ($authorization) {
$self->info("unauthorized remote inventory request for $remoteid");
$client->send_error(403);
return 403;
}
$self->debug("remote inventory request for $remoteid");
my $agent = $self->{server}->{agent};
my $task = FusionInventory::Agent::Task::Inventory->new(
logger => $logger,
target => $target,
deviceid => $agent->{deviceid},
datadir => $agent->{datadir},
config => $agent->{config},
);
my $done;
{
local $SIG{CHLD} = sub {};
$done = $task->run();
}
unless ($done) {
$self->error("Failed to run inventory");
$client->send_error(500, "Inventory failure");
return 500;
}
my $data = $target->inventory_xml();
my $content_type = 'application/xml';
my @accept = split(/, */,$request->header('accept') || '');
# check compression mode
if (!$self->{no_compress} && Compress::Zlib->require() && grep { m|application/x-compress-zlib| } @accept) {
# RFC 1950
$content_type = 'application/x-compress-zlib';
$self->debug('Using Compress::Zlib for compression');
$data = Compress::Zlib::compress($data);
} elsif (!$self->{no_compress} && canRun('gzip') && grep { m|application/x-compress-gzip| } @accept) {
# RFC 1952
$content_type = 'application/x-compress-gzip';
$self->debug('Using gzip for compression');
File::Temp->require();
my $fd = File::Temp->new();
print $fd $data;
close $fd;
my $out = getFileHandle(
command => 'gzip -c ' . $fd->filename(),
logger => $self->{logger}
);
next unless $out;
local $INPUT_RECORD_SEPARATOR; # Set input to "slurp" mode.
$data = <$out>;
close $out;
}
my $response = HTTP::Response->new(
200,
'OK',
HTTP::Headers->new( 'Content-Type' => $content_type ),
$data
);
$client->send_response($response);
$self->info("Inventory returned to $remoteid");
$self->{keepalive} = 0;
return 200;
}
sub keepalive {
my ($self) = @_;
# Always reset the keepalive state
return delete $self->{keepalive};
}
1;
__END__
=head1 NAME
FusionInventory::Agent::HTTP::Server::Inventory - An embedded HTTP server plugin
providing remote inventory
=head1 DESCRIPTION
This is a server plugin to listen for inventory requests.
It listens on port 62354 by default and can answer with a full inventory XML if
authorized.
The following default requests are accepted:
=over
=item /inventory/session
=item /inventory/get
=item /inventory/apiversion
=back
Authentication is firstly based on connection source address: trusted requests
can access the API. But a shared secret must be known to use the API.
A client must request a session before being able to request an inventory.
A 'X-Request-ID' header must be provided for a session creation:
The session permits to control access with a shared secret or token so an
inventory can only be provided if the returned payload matches the expected one.
The server answers with a nonce set in the 'X-Auth-Nonce' header.
For the /get call, the client must still provide a 'X-Request-ID' header but it
also must provide a 'X-Auth-Payload' one computed from 'X-Auth-Nonce' provided
value and the shared secret.
=head1 CONFIGURATION
=over
=item disabled C<yes> by default
=item url_path C</inventory> by default
=item port C<0> by default to use default one
=item token not defined by default. /get API is disabled untill one is set
=item session_timeout C<60> (in seconds) by default.
=item maxrate C<30> by default
=item maxrate_period C<3600> (in seconds) by default.
=item no_compress C<no> by default to keep XML compression possible.
=back
Defaults can be overrided in C<inventory-server-plugin.cfg> file or better in the
C<inventory-server-plugin.local> if included from C<inventory-server-plugin.cfg>.
package FusionInventory::Agent::HTTP::Server::Plugin;
use strict;
use warnings;
use base "FusionInventory::Agent::Config";
use Cwd qw(abs_path);
use FusionInventory::Agent::Tools;
sub new {
my ($class, %params) = @_;
my ($name) = $class =~ /::(\w+)$/;
my $self = {
logger => $params{server}->{logger} ||
FusionInventory::Agent::Logger->new(),
server => $params{server},
name => $name,
};
bless $self, $class;
# Check _confdir imported from FusionInventory::Agent::Config
unless ($self->{_confdir} && -d $self->{_confdir}) {
# Set absolute confdir from default if replaced by Makefile otherwise search
# from current path, mostly useful while running from source
$self->{_confdir} = abs_path(File::Spec->rel2abs(
$self->{_confdir} || first { -d $_ } qw{ ./etc ../etc }
));
}
return $self;
}
sub init {
my ($self) = @_;
$self->debug("Initializing ".$self->{name}." Server plugin...");
# Load defaults
my $defaults = $self->defaults();
foreach my $param (keys(%{$defaults})) {
$self->{$param} = $defaults->{$param};
}
if ($self->confdir() && $self->config_file()) {
my $config = $self->confdir().'/'.$self->config_file();
if (-f $config && -r $config) {
$self->debug("Loading ".$self->{name}." Server plugin configuration from $config");
# Load configuration file
$self->loadFromFile({file => $config, defaults => $defaults});
} else {
$self->debug($self->{name}." Server plugin configuration missing: $config");
}
}
}
# Plugins with greater priority values are used first
sub priority { 10 }
sub name {
my ($self) = @_;
return $self->{name};
}
# Defaults must be a key-value pair list ref if and only if a config file
# is to be read while config_file() method returns a config filename
sub defaults {
return {};
}
sub supported_method {
my ($self, $method) = @_;