forked from Velocidex/velociraptor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add artifact for installing and configuring deb packages (Velocidex#3626
) In Debian-based OSes software is preferably installed through the package manager. This artifact provides a comfortable way to install packages, as well as configuring them using debconf. The package can either be a name or a deb file, which can be optionally uploaded. The purpose is to provide a reusable component for installing and configuring tools and other packages needed by other artifacts in a single command. `apt-get update` is optionally run, and dependencies, if any, is automatically installed. debconf may be pre-seeded with answers if the package requires configuration. Other artifacts can offload all installation and configuration logic to this artifact by calling it like this: `SELECT * FROM Artifact.Linux.Utils.InstallDeb(DebName='sl')` or `SELECT * FROM Artifact.Linux.Utils.InstallDeb(DebName='/tmp/mypackage_0.1.0-1_amd64.deb')`. A row with *Step* "Installing package" and *ReturnCode* 0 will indicate that the installation was a success.
- Loading branch information
Showing
1 changed file
with
178 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
name: Linux.Utils.InstallDeb | ||
author: Andreas Misje – @misje | ||
description: | | ||
Install a deb package and configure it with debconf answers. The package | ||
may either be specified by name or be an uploaded file. If the package | ||
already exists, it may be optionally reconfigured with debconf answers. | ||
type: CLIENT | ||
|
||
required_permissions: | ||
- EXECVE | ||
|
||
reference: | ||
- https://manpages.debian.org/bookworm/debconf-doc/debconf-devel.7.en.html#Type | ||
|
||
parameters: | ||
- name: DebName | ||
description: | | ||
Package to install (by name). Ignored if DebFile is set. An absolute path | ||
to a deb file that already exists on the system is also accepted. | ||
- name: DebFile | ||
description: | | ||
Package to install (by file). Remember to click "Upload"! When set, | ||
DebName is ignored. Use DebName with an absolute file path if the | ||
file already exists on the system and does not need to be uploaded. | ||
type: upload | ||
|
||
- name: UpdateSources | ||
description: | | ||
Run `apt-get update` before installing the package. This is not necessary | ||
if the package has no dependencies, and it should be disabled if there | ||
is no Internet. | ||
type: bool | ||
default: True | ||
|
||
- name: ForceConfNew | ||
type: bool | ||
description: | | ||
Use the configuration delivered by the package instead of keeping the | ||
local changes. | ||
- name: ReconfigureIfInstalled | ||
type: bool | ||
description: | | ||
If the package is already installed, run pre-seed debconf and | ||
`dpkg-reconfigure` instead. | ||
- name: DebConfValues | ||
type: csv | ||
description: | | ||
debconf is a system used by many packages for interactive configuration. | ||
When using a non-interactive frontend (like this artifact), answers may | ||
by provided as a "pre-seed" file. Example line: | ||
"wireshark-common/install-setuid,boolean,false" | ||
default: | | ||
Key,Type,Value | ||
column_types: | ||
- name: Stdout | ||
type: nobreak | ||
|
||
- name: Stderr | ||
type: nobreak | ||
|
||
sources: | ||
- precondition: | ||
SELECT OS From info() where OS = 'linux' | ||
|
||
query: | | ||
LET Package <= if( | ||
condition=DebFile, | ||
then=tempfile(data=DebFile, extension='_amd64.deb'), | ||
else=DebName) | ||
/* The file name is lost from the uploaded file, so extract it from the | ||
package instead: */ | ||
LET PackageInfo = SELECT Stdout | ||
FROM execve(argv=['/usr/bin/dpkg-deb', '--field', Package, 'Package']) | ||
LET PackageName = if( | ||
condition=DebFile, | ||
then=PackageInfo[0].Stdout[:-1], // remove "\n" | ||
else=DebName) | ||
/* The file format is "package_name question type answer": */ | ||
LET PreSeedLines = SELECT | ||
join( | ||
sep=' ', | ||
array=(PackageName, Key, Type, Value, )) AS Line | ||
FROM DebConfValues | ||
LET PreSeedFile <= tempfile(data=join(sep='\n', array=PreSeedLines.Line)) | ||
LET AptOpts <= ('-f', '-y', '-o', 'Debug::pkgProblemResolver=yes', '--no-install-recommends', ) + if( | ||
condition=ForceConfNew, | ||
then=('-o', 'Dpkg::Options::="--force-confnew"', ), | ||
else=[]) | ||
LET PreSeed = SELECT | ||
'Pre-seed debconf' AS Step, | ||
* | ||
FROM if( | ||
condition=DebConfValues, | ||
then={ | ||
SELECT * | ||
FROM execve(argv=['/usr/bin/debconf-set-selections', PreSeedFile, ]) | ||
WHERE log( | ||
message=format( | ||
format='Pre-seeding %v', | ||
args=[PackageName, ]), | ||
level='INFO') | ||
}) | ||
LET Install = SELECT * | ||
FROM chain( | ||
a_update={ | ||
SELECT | ||
'Update index' AS Step, | ||
* | ||
FROM if( | ||
condition=UpdateSources, | ||
then={ | ||
SELECT * | ||
FROM execve(argv=['/usr/bin/apt-get', '-y', 'update']) | ||
WHERE log( | ||
message='Updating package index before installing', | ||
level='INFO') | ||
}) | ||
}, | ||
b_debconf=PreSeed, | ||
c_install={ | ||
SELECT | ||
'Installing package' AS Step, | ||
* | ||
FROM execve(argv=('/usr/bin/apt-get', 'install', ) + AptOpts + (Package, )) | ||
WHERE log( | ||
message=format( | ||
format='Installing deb package %v', | ||
args=[PackageName, ]), | ||
level='INFO') | ||
}) | ||
LET IsInstalled = SELECT * | ||
FROM stat( | ||
filename=path_join( | ||
components=('/var/lib/dpkg/info', PackageName + '.list'))) | ||
WHERE log( | ||
message=format( | ||
format='Package %v is already installed', | ||
args=[PackageName, ]), | ||
level='INFO') | ||
SELECT * | ||
FROM if( | ||
condition=IsInstalled, | ||
then=if( | ||
condition=ReconfigureIfInstalled, | ||
then={ | ||
SELECT * | ||
FROM chain( | ||
a_debconf=PreSeed, | ||
b_reconfigure={ | ||
SELECT | ||
'Reconfiguring package' AS Step, | ||
* | ||
FROM execve(argv=['/usr/sbin/dpkg-reconfigure', PackageName, ], | ||
env=dict( | ||
DEBIAN_FRONTEND='noninteractive')) | ||
WHERE log( | ||
message=format( | ||
format='Reconfiguring deb package %v', | ||
args=[PackageName, ]), | ||
level='INFO') | ||
}) | ||
}), | ||
else=Install) |