Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sidecars): add & bind ClamAV build from source for Debian & macOS #150

Merged
merged 31 commits into from
Aug 30, 2024

Conversation

ivangabriele
Copy link
Owner

@ivangabriele ivangabriele commented Aug 29, 2024

Description

Build ClamAV standalone binaries for Debian & macOS and embed them into Core as sidecars.

Checklist

  • I updated the documentation accordingly. Or I don't need to.
  • I updated the tests accordingly. Or I don't need to.

@ivangabriele ivangabriele added os:debian feature:approved Approved new feature or feature enhancement. labels Aug 29, 2024
@ivangabriele ivangabriele added this to the v0.4 milestone Aug 29, 2024
@codecov-commenter
Copy link

codecov-commenter commented Aug 29, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 36.94%. Comparing base (c5f7a65) to head (32d4097).
Report is 31 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #150      +/-   ##
==========================================
- Coverage   37.91%   36.94%   -0.98%     
==========================================
  Files          23       23              
  Lines         720      720              
  Branches        2        2              
==========================================
- Hits          273      266       -7     
- Misses        447      454       +7     
Flag Coverage Δ
core 37.35% <ø> (-1.01%) ⬇️
webview 25.00% <ø> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ivangabriele ivangabriele changed the title feat(sidecars): add & bind ClamAV build from source for Linux feat(sidecars): add & bind ClamAV build from source for Linux & macOS Aug 30, 2024
@ivangabriele ivangabriele changed the title feat(sidecars): add & bind ClamAV build from source for Linux & macOS feat(sidecars): add & bind ClamAV build from source for Debian & macOS Aug 30, 2024
@ivangabriele ivangabriele marked this pull request as ready for review August 30, 2024 08:05
Copy link

coderabbitai bot commented Aug 30, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The changes involve updates to various GitHub Actions workflow files, enhancements to build scripts, and modifications to Rust source files. Key adjustments include upgrading Node.js versions, refining Rust toolchain setups, and introducing new scripts for dependency installation on Debian and macOS. Additionally, several functions related to ClamAV have been added or modified to streamline the build process and improve clarity in the codebase, alongside adjustments to the .gitignore and .yarnrc.yml files.

Changes

File(s) Change Summary
.github/workflows/*.yml Updated Node.js version from 20 to 22; removed submodules option from checkout steps.
Makefile Added setup-debian and setup-macos targets for OS-specific development environment setup.
scripts/build/actions/*.js Introduced functions for building ClamAV from source, managing sidecars, and downloading source code.
scripts/dev/*.sh Added scripts for installing development requirements on Debian and macOS.
.gitignore Modified patterns to ignore entire directories instead of individual files.
.yarnrc.yml Removed options for global cache and Yarn path, simplifying configuration.
src-tauri/dev/src/lib.rs Updated path construction in get_debug_clamd_conf_file_path function.
src-tauri/src/settings/utils.rs Consolidated error logging in get_clamd_conf_file_path and removed unnecessary module declaration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CI
    participant BuildSystem
    participant ClamAV

    User->>CI: Trigger build
    CI->>BuildSystem: Setup environment
    BuildSystem->>ClamAV: Download source
    ClamAV-->>BuildSystem: Source downloaded
    BuildSystem->>ClamAV: Build from source
    ClamAV-->>BuildSystem: Build successful
    BuildSystem->>CI: Build artifacts ready
    CI-->>User: Notify build completion
Loading

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Comment on lines +1 to +13
#!/bin/bash
set -e

# https://docs.clamav.net/manual/Installing/Installing-from-source-Unix.html#ubuntu--debian

apt-get update && apt-get install -y \
`# install tools` \
gcc make pkg-config python3 python3-pip python3-pytest valgrind cmake \
`# install clamav dependencies` \
check libbz2-dev libcurl4-openssl-dev libjson-c-dev libmilter-dev \
libncurses5-dev libpcre2-dev libssl-dev libxml2-dev zlib1g-dev \
`# install ninja for faster builds` \
ninja-build
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider handling non-root user scenarios.

The script assumes that it is being run with root privileges. Consider checking for root access at the beginning of the script or providing instructions on how to run the script with sudo if necessary.

Comment on lines +1 to +16
#!/bin/bash
set -e

# https://docs.clamav.net/manual/Installing/Installing-from-source-Unix.html#macos

brew update

packages=(
# install tools
python3 cmake
# install clamav dependencies
bzip2 check curl-openssl json-c libxml2 ncurses [email protected] pcre2 zlib
)
for item in "${packages[@]}"; do
brew install $item || true; brew upgrade $item || brew upgrade $item
done
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance script robustness by addressing static analysis flags.

The script setup and package installation commands are generally well-implemented. However, consider adding double quotes around $item in the brew install and brew upgrade commands to prevent globbing and word splitting, as suggested by static analysis.

Apply this diff to enhance the script's robustness:

-for item in "${packages[@]}"; do
-  brew install $item || true; brew upgrade $item || brew upgrade $item
+for item in "${packages[@]}"; do
+  brew install "$item" || true; brew upgrade "$item" || brew upgrade "$item"
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#!/bin/bash
set -e
# https://docs.clamav.net/manual/Installing/Installing-from-source-Unix.html#macos
brew update
packages=(
# install tools
python3 cmake
# install clamav dependencies
bzip2 check curl-openssl json-c libxml2 ncurses [email protected] pcre2 zlib
)
for item in "${packages[@]}"; do
brew install $item || true; brew upgrade $item || brew upgrade $item
done
#!/bin/bash
set -e
# https://docs.clamav.net/manual/Installing/Installing-from-source-Unix.html#macos
brew update
packages=(
# install tools
python3 cmake
# install clamav dependencies
bzip2 check curl-openssl json-c libxml2 ncurses [email protected] pcre2 zlib
)
for item in "${packages[@]}"; do
brew install "$item" || true; brew upgrade "$item" || brew upgrade "$item"
done
Tools
Shellcheck

[info] 15-15: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 15-15: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 15-15: Double quote to prevent globbing and word splitting.

(SC2086)

@@ -16,7 +16,7 @@ fn construct_path_from_root(root_path: &str, relative_path: &[&str]) -> String {

#[cfg(not(tarpaulin_include))]
pub fn get_debug_clamd_conf_file_path() -> String {
construct_path_from_root("", &["..", ".debug", "clamd.conf"])
construct_path_from_root("", &["..", ".dev", "clamd.conf"])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Directory or configuration file missing

The .dev directory or the clamd.conf file does not exist, which could lead to runtime errors. Please ensure that the .dev directory is correctly set up and contains the necessary configuration file. This change in the path suggests a shift in the development workflow, and proper configuration is essential.

Analysis chain

Verify the new directory configuration.

The change from .debug to .dev in the path suggests a shift in the development workflow. Ensure that the .dev directory exists and is correctly configured to avoid runtime errors.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the .dev directory and its configuration.

# Test: Check if the .dev directory exists and contains clamd.conf.
if [ -d "../.dev" ] && [ -f "../.dev/clamd.conf" ]; then
  echo "Directory and configuration file exist."
else
  echo "Directory or configuration file does not exist."
fi

Length of output: 125

Comment on lines +6 to +38
export async function buildTranslatorSidecars(rootPath) {
// We only need translator sidecars for Windows since we need to embed its entire standalone build directory
// for the binaries to work. For Linux and macOS, we build ClamAV standalone binaries from source,
// which means their binaries can be directly used as sidecars.
if (process.platform !== 'win32') {
B.info('[prepare_core_build.js]', 'Not a Windows machine. Skipping translator sidecars build...')

return
}

const sourceDirectoryPath = join(rootPath, 'sidecars')
const releaseDirectoryPath = join(sourceDirectoryPath, 'target/release')
const sidecarsDirectoryPath = join(rootPath, 'src-tauri/sidecars')

B.info('[prepare_core_build.js]', 'Building translator sidecars...')
const buildConfigResponse = await execa('cargo', ['build', '--release'], {
cwd: sourceDirectoryPath,
reject: false,
stdio: 'inherit',
})
if (buildConfigResponse.failed) {
B.error('[prepare_core_build.js]', 'Translator sidecars build failed.')

process.exit(1)
}

B.info('[prepare_core_build.js]', 'Moving translator sidecar binaries into sidecars directory...')
await fs.rename(join(releaseDirectoryPath, 'clamd.exe'), join(sidecarsDirectoryPath, 'clamd.exe'))
await fs.rename(join(releaseDirectoryPath, 'clamscan.exe'), join(sidecarsDirectoryPath, 'clamscan.exe'))
await fs.rename(join(releaseDirectoryPath, 'freshclam.exe'), join(sidecarsDirectoryPath, 'freshclam.exe'))

B.success('[prepare_core_build.js]', 'Translator sidecars successfully built.')
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve the platform-specific build logic and suggest enhanced error handling.

The script correctly handles platform-specific conditions and uses external tools effectively. Consider replacing process.exit(1) with throwing an error to allow for better error handling in scenarios where this script might be used as part of larger automation processes.

Comment on lines +43 to +52
await downloadClamavBuild(CONTROLLED_TARGET, ROOT_PATH)

B.info('[prepare_core_build.js]', 'Building translator sidecars...')
await buildTranslatorSidecars(ROOT_PATH)

B.info('[prepare_core_build.js]', 'Downloading ClamAV source...')
await downloadClamavSource(ROOT_PATH)

B.info('[prepare_core_build.js]', 'Building ClamAV from source...')
await buildClamavFromSource(ROOT_PATH)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logical sequence of function calls, but consider enhancing logging for clarity.

The sequence of function calls is logically structured to ensure all components are prepared in the correct order. However, consider adding more detailed logging at each step to provide clearer insights into the process, especially useful during debugging or failure analysis.

Add more detailed logs before each major action:

+ B.info('[prepare_core_build.js]', 'Starting download of ClamAV build...')
  await downloadClamavBuild(CONTROLLED_TARGET, ROOT_PATH)
+ B.info('[prepare_core_build.js]', 'Starting build of translator sidecars...')
  await buildTranslatorSidecars(ROOT_PATH)
+ B.info('[prepare_core_build.js]', 'Starting download of ClamAV source...')
  await downloadClamavSource(ROOT_PATH)
+ B.info('[prepare_core_build.js]', 'Starting build of ClamAV from source...')
  await buildClamavFromSource(ROOT_PATH)
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await downloadClamavBuild(CONTROLLED_TARGET, ROOT_PATH)
B.info('[prepare_core_build.js]', 'Building translator sidecars...')
await buildTranslatorSidecars(ROOT_PATH)
B.info('[prepare_core_build.js]', 'Downloading ClamAV source...')
await downloadClamavSource(ROOT_PATH)
B.info('[prepare_core_build.js]', 'Building ClamAV from source...')
await buildClamavFromSource(ROOT_PATH)
B.info('[prepare_core_build.js]', 'Starting download of ClamAV build...')
await downloadClamavBuild(CONTROLLED_TARGET, ROOT_PATH)
B.info('[prepare_core_build.js]', 'Starting build of translator sidecars...')
await buildTranslatorSidecars(ROOT_PATH)
B.info('[prepare_core_build.js]', 'Starting download of ClamAV source...')
await downloadClamavSource(ROOT_PATH)
B.info('[prepare_core_build.js]', 'Starting build of ClamAV from source...')
await buildClamavFromSource(ROOT_PATH)

Comment on lines +9 to +54
export async function buildClamavFromSource(rootPath) {
// We only build ClamAV binaries from source for Linux and macOS. For Windows, we download the build.
if (!['darwin', 'linux'].includes(process.platform)) {
B.info('[prepare_core_build.js]', 'Not a Linux or macOS machine. Skipping ClamAV build...')

return
}

const sourceDirectoryPath = join(rootPath, '.dev/clamav')
const buildDirectoryPath = join(sourceDirectoryPath, 'build')
const sidecarsDirectoryPath = join(rootPath, 'src-tauri/sidecars')

B.info('[prepare_core_build.js]', 'Preparing ClamAV build...')
await fs.mkdir(buildDirectoryPath, { recursive: true })

B.info('[prepare_core_build.js]', 'Configuring ClamAV build...')
const buildConfigResponse = await execa('cmake', ['..', '-G', 'Ninja', '-D', 'CMAKE_BUILD_TYPE=Release'], {
cwd: buildDirectoryPath,
reject: false,
stdio: 'inherit',
})
if (buildConfigResponse.failed) {
B.error('[prepare_core_build.js]', 'ClamAV build failed.')

process.exit(1)
}

B.info('[prepare_core_build.js]', 'Building ClamAV...')
const buildResponse = await execa('cmake', ['--build', '.'], {
cwd: buildDirectoryPath,
reject: false,
stdio: 'inherit',
})
if (buildResponse.failed) {
B.error('[prepare_core_build.js]', 'ClamAV build failed.')

process.exit(1)
}

B.info('[prepare_core_build.js]', 'Moving ClamAV binaries into sidecars directory...')
await fs.rename(join(buildDirectoryPath, 'clamd/clamd'), join(sidecarsDirectoryPath, 'clamd'))
await fs.rename(join(buildDirectoryPath, 'clamscan/clamscan'), join(sidecarsDirectoryPath, 'clamscan'))
await fs.rename(join(buildDirectoryPath, 'freshclam/freshclam'), join(sidecarsDirectoryPath, 'freshclam'))

B.success('[prepare_core_build.js]', 'ClamAV successfully built.')
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well-structured function, but improve error handling.

The function buildClamavFromSource is well-structured and includes necessary checks for platform compatibility and directory management. However, consider handling errors more explicitly rather than using reject: false in execa calls, which might suppress important errors.

Modify the execa calls to handle errors more explicitly:

- const buildConfigResponse = await execa('cmake', ['..', '-G', 'Ninja', '-D', 'CMAKE_BUILD_TYPE=Release'], {
-   cwd: buildDirectoryPath,
-   reject: false,
-   stdio: 'inherit',
- })
+ const buildConfigResponse = await execa('cmake', ['..', '-G', 'Ninja', '-D', 'CMAKE_BUILD_TYPE=Release'], {
+   cwd: buildDirectoryPath,
+   stdio: 'inherit',
+ }).catch(error => {
+   B.error('[prepare_core_build.js]', 'ClamAV build configuration failed:', error)
+   process.exit(1)
+ })
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function buildClamavFromSource(rootPath) {
// We only build ClamAV binaries from source for Linux and macOS. For Windows, we download the build.
if (!['darwin', 'linux'].includes(process.platform)) {
B.info('[prepare_core_build.js]', 'Not a Linux or macOS machine. Skipping ClamAV build...')
return
}
const sourceDirectoryPath = join(rootPath, '.dev/clamav')
const buildDirectoryPath = join(sourceDirectoryPath, 'build')
const sidecarsDirectoryPath = join(rootPath, 'src-tauri/sidecars')
B.info('[prepare_core_build.js]', 'Preparing ClamAV build...')
await fs.mkdir(buildDirectoryPath, { recursive: true })
B.info('[prepare_core_build.js]', 'Configuring ClamAV build...')
const buildConfigResponse = await execa('cmake', ['..', '-G', 'Ninja', '-D', 'CMAKE_BUILD_TYPE=Release'], {
cwd: buildDirectoryPath,
reject: false,
stdio: 'inherit',
})
if (buildConfigResponse.failed) {
B.error('[prepare_core_build.js]', 'ClamAV build failed.')
process.exit(1)
}
B.info('[prepare_core_build.js]', 'Building ClamAV...')
const buildResponse = await execa('cmake', ['--build', '.'], {
cwd: buildDirectoryPath,
reject: false,
stdio: 'inherit',
})
if (buildResponse.failed) {
B.error('[prepare_core_build.js]', 'ClamAV build failed.')
process.exit(1)
}
B.info('[prepare_core_build.js]', 'Moving ClamAV binaries into sidecars directory...')
await fs.rename(join(buildDirectoryPath, 'clamd/clamd'), join(sidecarsDirectoryPath, 'clamd'))
await fs.rename(join(buildDirectoryPath, 'clamscan/clamscan'), join(sidecarsDirectoryPath, 'clamscan'))
await fs.rename(join(buildDirectoryPath, 'freshclam/freshclam'), join(sidecarsDirectoryPath, 'freshclam'))
B.success('[prepare_core_build.js]', 'ClamAV successfully built.')
}
export async function buildClamavFromSource(rootPath) {
// We only build ClamAV binaries from source for Linux and macOS. For Windows, we download the build.
if (!['darwin', 'linux'].includes(process.platform)) {
B.info('[prepare_core_build.js]', 'Not a Linux or macOS machine. Skipping ClamAV build...')
return
}
const sourceDirectoryPath = join(rootPath, '.dev/clamav')
const buildDirectoryPath = join(sourceDirectoryPath, 'build')
const sidecarsDirectoryPath = join(rootPath, 'src-tauri/sidecars')
B.info('[prepare_core_build.js]', 'Preparing ClamAV build...')
await fs.mkdir(buildDirectoryPath, { recursive: true })
B.info('[prepare_core_build.js]', 'Configuring ClamAV build...')
const buildConfigResponse = await execa('cmake', ['..', '-G', 'Ninja', '-D', 'CMAKE_BUILD_TYPE=Release'], {
cwd: buildDirectoryPath,
stdio: 'inherit',
}).catch(error => {
B.error('[prepare_core_build.js]', 'ClamAV build configuration failed:', error)
process.exit(1)
})
if (buildConfigResponse.failed) {
B.error('[prepare_core_build.js]', 'ClamAV build failed.')
process.exit(1)
}
B.info('[prepare_core_build.js]', 'Building ClamAV...')
const buildResponse = await execa('cmake', ['--build', '.'], {
cwd: buildDirectoryPath,
reject: false,
stdio: 'inherit',
})
if (buildResponse.failed) {
B.error('[prepare_core_build.js]', 'ClamAV build failed.')
process.exit(1)
}
B.info('[prepare_core_build.js]', 'Moving ClamAV binaries into sidecars directory...')
await fs.rename(join(buildDirectoryPath, 'clamd/clamd'), join(sidecarsDirectoryPath, 'clamd'))
await fs.rename(join(buildDirectoryPath, 'clamscan/clamscan'), join(sidecarsDirectoryPath, 'clamscan'))
await fs.rename(join(buildDirectoryPath, 'freshclam/freshclam'), join(sidecarsDirectoryPath, 'freshclam'))
B.success('[prepare_core_build.js]', 'ClamAV successfully built.')
}

@@ -124,7 +139,7 @@ jobs:
# uses: actions/setup-node@v4
# with:
# cache: yarn
# node-version: 20
# node-version: 22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged: Commented-out code for potential ARM64 builds.

The commented-out sections related to ARM64 builds do not affect the current functionality but indicate ongoing development considerations for future configurations.

Comment on lines +10 to +105
/**
* Download ClamAV source for Linux and macOS.
*/
export async function downloadClamavSource(rootPath) {
// We only build ClamAV binaries from source for Linux and macOS. For Windows, we download the build.
if (!['darwin', 'linux'].includes(process.platform)) {
B.info('[prepare_core_build.js]', 'Not a Linux or macOS machine. Skipping source download...')

return
}

const metaSource = await fs.readFile(`${rootPath}/src-tauri/resources/meta.json`, 'utf8')
const meta = JSON.parse(metaSource)

const clamavVersion = meta.clamav.version
const devDirectoryPath = join(rootPath, '.dev')
const signaturePublicKeyPath = join(rootPath, 'scripts/build/cisco-talos-gpg-public-key.asc')

const downloadedSourceDirectoryPath = join(devDirectoryPath, `clamav-${clamavVersion}`)
const downloadedSourceArchivePath = `${downloadedSourceDirectoryPath}.tar.gz`
const downloadedSourceArchiveSignaturePath = `${downloadedSourceArchivePath}.sig`
const targetSourceDirectoryPath = join(devDirectoryPath, 'clamav')

if (existsSync(targetSourceDirectoryPath)) {
B.info('[prepare_core_build.js]', 'ClamAV source already downloaded. Skipping source download...')

return
}

// -----------------------------------------------------------------------------
// Download ClamAV source

const buildDownloadUrl = [
'https://github.com/Cisco-Talos/clamav/releases/download',
`clamav-${clamavVersion}`,
`clamav-${clamavVersion}.tar.gz`,
].join('/')
const signatureDownloadUrl = `${buildDownloadUrl}.sig`

B.log('[prepare_core_build.js]', `Downloading ClamAV v${clamavVersion} source...`)
await download(buildDownloadUrl, devDirectoryPath)
B.log('[prepare_core_build.js]', `Downloading ClamAV v${clamavVersion} source signature...`)
await download(signatureDownloadUrl, devDirectoryPath)

// -----------------------------------------------------------------------------
// Verify ClamAV source signature

B.log('[prepare_core_build.js]', `Verifying ClamAV v${clamavVersion} source signature...`)
const publicKeyArmored = await fs.readFile(signaturePublicKeyPath, 'utf8')
const signatureArmored = await fs.readFile(downloadedSourceArchiveSignaturePath, 'utf8')
const zipFile = await fs.readFile(downloadedSourceArchivePath)

const publicKey = await readKey({ armoredKey: publicKeyArmored })
const signature = await readSignature({ armoredSignature: signatureArmored })
const verificationResult = await verify({
message: await createMessage({ binary: zipFile }),
signature: signature,
verificationKeys: publicKey,
config: {
// Seems to be hashed with SHA1
// (to avoid: `Error: Insecure message hash algorithm: SHA1`)
// https://github.com/openpgpjs/openpgpjs/blob/main/src/config/config.js#L241
rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]),
},
})

try {
await verificationResult.signatures[0].verified // Throws an error if verification fails
} catch (err) {
B.error('[prepare_core_build.js]', `ClamAV v${clamavVersion} source signature verification failed.`)
console.error(err)

process.exit(1)
}

// -----------------------------------------------------------------------------
// Extract ClamAV source

B.log('[prepare_core_build.js]', `Extracting ClamAV v${clamavVersion} source...`)
await decompress(downloadedSourceArchivePath, devDirectoryPath)

// -----------------------------------------------------------------------------
// Clean up downloaded files

B.log('[prepare_core_build.js]', 'Cleaning up downloaded archive & signature...')
await deleteAsync([downloadedSourceArchivePath, downloadedSourceArchiveSignaturePath])

// -----------------------------------------------------------------------------
// Normalize extracted directory name

B.log('[prepare_core_build.js]', 'Normalizing extracted directory name...')
await move(downloadedSourceDirectoryPath, targetSourceDirectoryPath)

// -----------------------------------------------------------------------------

B.success('[prepare_core_build.js]', `ClamAV v${clamavVersion} source successfully downloaded.`)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance error handling and platform checking.

The function correctly implements the downloading and verification of ClamAV source for Linux and macOS. Consider enhancing the robustness of the platform checking and improving error handling during the download and verification steps to prevent runtime errors and ensure a smoother operation.

Enhance the platform checking logic to be more robust and improve error handling mechanisms to handle potential download and verification failures more gracefully.

@ivangabriele ivangabriele merged commit f2781df into main Aug 30, 2024
16 checks passed
@ivangabriele ivangabriele deleted the ivan/feat-sidecars-add-linux-bindings branch August 30, 2024 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature:approved Approved new feature or feature enhancement. os:debian os:macos
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants