From 94287ed8d45df4fce34c0cde96281c2159681d90 Mon Sep 17 00:00:00 2001 From: Matisse Brard Date: Thu, 27 Feb 2025 10:10:06 +0100 Subject: [PATCH 1/3] fix: append OS and architecture to artifact name to prevent upload conflicts --- .github/workflows/release-lgc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-lgc.yml b/.github/workflows/release-lgc.yml index 73c6f75..7ce43b4 100644 --- a/.github/workflows/release-lgc.yml +++ b/.github/workflows/release-lgc.yml @@ -38,7 +38,7 @@ jobs: - name: Upload CLI Artifacts uses: actions/upload-artifact@v4 with: - name: lgc + name: lgc-${{ steps.toLowerCase.outputs.osLowercase }}-${{ steps.toLowerCase.outputs.archLowercase }}-tarballs path: | releases/lgc-${{ steps.toLowerCase.outputs.osLowercase }}-${{ steps.toLowerCase.outputs.archLowercase }}.tar.gz releases/lgc-${{ steps.toLowerCase.outputs.osLowercase }}-${{ steps.toLowerCase.outputs.archLowercase }}.tar.gz.sha256 From 74f28a55908060eb320c691bb639480934945ac7 Mon Sep 17 00:00:00 2001 From: Matisse Brard Date: Thu, 27 Feb 2025 10:12:12 +0100 Subject: [PATCH 2/3] chore: standardize Docker image tag by removing lgc prefix from version --- .github/workflows/release-image.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release-image.yml b/.github/workflows/release-image.yml index 70c4a7e..1c9bcfa 100644 --- a/.github/workflows/release-image.yml +++ b/.github/workflows/release-image.yml @@ -23,21 +23,17 @@ jobs: uses: actions/checkout@v4 # Install the cosign tool except on PR - # https://github.com/sigstore/cosign-installer - name: Install cosign if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0 + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 with: cosign-release: 'v2.2.4' - # Set up BuildKit Docker container builder to be able to build - # multi-platform images and export cache - # https://github.com/docker/setup-buildx-action + # Set up BuildKit Docker container builder - name: Set up Docker Buildx uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 # Login against a Docker registry except on PR - # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 @@ -47,15 +43,15 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # Remove the "lgc/" prefix from the git tag (e.g. "lgc/v1.0.0" becomes "v1.0.0") + tags: ${{ replace(github.ref_name, 'lgc/', '') }} # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action - name: Build and push Docker image id: build-and-push uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 @@ -69,16 +65,9 @@ jobs: cache-to: type=gha,mode=max # Sign the resulting Docker image digest except on PRs. - # This will only write to the public Rekor transparency log when the Docker - # repository is public to avoid leaking data. If you would like to publish - # transparency data even for private images, pass --force to cosign below. - # https://github.com/sigstore/cosign - name: Sign the published Docker image if: ${{ github.event_name != 'pull_request' }} env: - # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable TAGS: ${{ steps.meta.outputs.tags }} DIGEST: ${{ steps.build-and-push.outputs.digest }} - # This step uses the identity token to provision an ephemeral certificate - # against the sigstore community Fulcio instance. run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} \ No newline at end of file From ebd6f8cfa339bc4f9711078d7ccd6a165e5ccce0 Mon Sep 17 00:00:00 2001 From: Matisse Brard Date: Thu, 27 Feb 2025 11:11:12 +0100 Subject: [PATCH 3/3] fix: use base_dir for plugin retrieval --- apps/lgc/src/commands/apply.rs | 6 +++--- apps/lgc/src/commands/destroy.rs | 4 ++-- apps/lgc/src/commands/ping.rs | 2 +- apps/lgc/src/commands/plan.rs | 4 ++-- apps/lgc/src/commands/services.rs | 24 ++++++++++++++++-------- apps/lgc/src/commands/validate.rs | 2 +- libs/lgc-common/src/plugins/manager.rs | 24 +++++++++++------------- 7 files changed, 36 insertions(+), 30 deletions(-) diff --git a/apps/lgc/src/commands/apply.rs b/apps/lgc/src/commands/apply.rs index 196626b..d0494af 100644 --- a/apps/lgc/src/commands/apply.rs +++ b/apps/lgc/src/commands/apply.rs @@ -43,7 +43,7 @@ impl ApplyCommand { .join("plugins"); sync::Arc::make_mut(&mut context).retain(|name, _| { - let exists = plugins_dir.join(name).exists(); + let exists = plugins_dir.join(name).with_extension("wasm").exists(); if !exists { tracing::warn!( "folder `{}/{}` has no plugin associated.", @@ -65,7 +65,7 @@ impl ApplyCommand { let plugin_manager = PluginManager::new()?; let mut join_set = JoinSet::new(); for (plugin, context) in context.iter() { - let plugin_path = plugins_dir.join(plugin); + let plugin_path = plugins_dir.join(plugin).with_extension("wasm"); let plugin_manager = plugin_manager.clone(); // Cheap clone of context @@ -220,7 +220,7 @@ impl ApplyCommand { // Apply changes let plugin_manager = PluginManager::new()?; for (plugin, context) in context.iter() { - let plugin_path = plugins_dir.join(plugin); + let plugin_path = plugins_dir.join(plugin).with_extension("wasm"); let (instance, mut store) = plugin_manager.load_plugin(plugin_path).await?; // Cheap clone of context diff --git a/apps/lgc/src/commands/destroy.rs b/apps/lgc/src/commands/destroy.rs index c74d9e2..164f4f3 100644 --- a/apps/lgc/src/commands/destroy.rs +++ b/apps/lgc/src/commands/destroy.rs @@ -110,7 +110,7 @@ impl DestroyCommand { let mut join_set = JoinSet::new(); for (plugin, plugin_context) in detections { // Check if the plugin exists. - let plugin_path = plugins_dir.join(&plugin); + let plugin_path = plugins_dir.join(&plugin).with_extension("wasm"); if !plugin_path.exists() { tracing::warn!( "folder `{}/{}` has no plugin associated.", @@ -191,7 +191,7 @@ impl DestroyCommand { // Apply changes. let plugin_manager = PluginManager::new()?; for (plugin, services) in to_remove { - let plugin_path = plugins_dir.join(&plugin); + let plugin_path = plugins_dir.join(&plugin).with_extension("wasm"); let (instance, mut store) = plugin_manager.load_plugin(plugin_path).await?; for (service_name, rules) in services { for (path, settings, content) in rules { diff --git a/apps/lgc/src/commands/ping.rs b/apps/lgc/src/commands/ping.rs index ac1dc2c..1f67058 100644 --- a/apps/lgc/src/commands/ping.rs +++ b/apps/lgc/src/commands/ping.rs @@ -78,7 +78,7 @@ impl PingCommand { // For each service, spawn a separate task. for (plugin, service_list) in services { - let plugin_path = plugins_dir.join(&plugin); + let plugin_path = plugins_dir.join(&plugin).with_extension("wasm"); if !plugin_path.exists() { tracing::warn!( "folder `{}/{}` has no plugin associated.", diff --git a/apps/lgc/src/commands/plan.rs b/apps/lgc/src/commands/plan.rs index 0be12d3..bab1b61 100644 --- a/apps/lgc/src/commands/plan.rs +++ b/apps/lgc/src/commands/plan.rs @@ -51,7 +51,7 @@ impl PlanCommand { .join("plugins"); sync::Arc::make_mut(&mut context).retain(|name, _| { - let exists = plugins_dir.join(name).exists(); + let exists = plugins_dir.join(name).with_extension("wasm").exists(); if !exists { tracing::warn!( "folder `{}/{}` has no plugin associated.", @@ -76,7 +76,7 @@ impl PlanCommand { // Spawn a task per plugin that will retrieve the detections for all related services. for (plugin, context) in context.iter() { - let plugin_path = plugins_dir.join(plugin); + let plugin_path = plugins_dir.join(plugin).with_extension("wasm"); let plugin_manager = plugin_manager.clone(); // Cheap clone of context diff --git a/apps/lgc/src/commands/services.rs b/apps/lgc/src/commands/services.rs index 957b8c7..fd583b4 100644 --- a/apps/lgc/src/commands/services.rs +++ b/apps/lgc/src/commands/services.rs @@ -70,22 +70,28 @@ impl CreateService { // Determine plugin_name as an owned String let plugin_name: String = match self.plugin { - Some(plugin) => plugin, + Some(plugin) => { + // Check that the plugin actually exists + if !plugin_names.contains(&plugin) { + anyhow::bail!("plugin `{}` does not exist", plugin); + } + plugin + }, None => { let selection = dialoguer::Select::with_theme(&prompt_theme) .with_prompt("Select the plugin to use:") .items(&plugin_names) .default(0) .interact()?; - plugin_names[selection].clone() + + if let Some(plugin) = plugin_names.get(selection) { + plugin.to_string() + } else { + anyhow::bail!("plugin not found"); + } } }; - // Check that the plugin actually exists - if !plugin_names.contains(&plugin_name) { - anyhow::bail!("plugin `{}` does not exist", plugin_name); - } - // Prompt for service identifier if not provided let identifier: String = ensure_kebab_case(match self.identifier { Some(id) => id, @@ -127,7 +133,9 @@ impl CreateService { .interact()?; // Load plugin & configure plugin - let (instance, mut store) = plugin_manager.load_plugin(&plugin_name).await?; + let (instance, mut store) = plugin_manager.load_plugin( + plugins_dir.join(plugin_name).with_extension("wasm") + ).await?; service.configure(&instance.settings(&mut store).await?, use_default)?; tracing::info!("service `{identifier}` successfully created"); diff --git a/apps/lgc/src/commands/validate.rs b/apps/lgc/src/commands/validate.rs index c0932af..5557462 100644 --- a/apps/lgc/src/commands/validate.rs +++ b/apps/lgc/src/commands/validate.rs @@ -38,7 +38,7 @@ impl ValidateCommand { // Instantiate plugins & validate detections for plugin in plugin_names { // Check if the plugin exists. - let plugin_path = plugins_dir.join(&plugin); + let plugin_path = plugins_dir.join(&plugin).with_extension("wasm"); if !plugin_path.exists() { tracing::warn!( "folder `{}/{}` has no plugin associated.", diff --git a/libs/lgc-common/src/plugins/manager.rs b/libs/lgc-common/src/plugins/manager.rs index 230d8ff..ff21985 100644 --- a/libs/lgc-common/src/plugins/manager.rs +++ b/libs/lgc-common/src/plugins/manager.rs @@ -67,20 +67,18 @@ impl PluginManager { } pub fn plugin_names(&self, base_dir: impl AsRef) -> anyhow::Result> { - let mut plugins = Vec::new(); - - if base_dir.as_ref().exists() { - for entry in fs::read_dir(base_dir)? { - let entry = entry?; - if entry.file_type()?.is_file() { - plugins.push(entry.file_name().to_string_lossy().to_string()); + fs::read_dir(base_dir) + .map(|entries| { + entries.filter_map(|entry| { + let path = entry.ok()?.path(); + if path.extension()?.to_str()? == "wasm" { + path.file_stem()?.to_str().map(String::from) + } else { + None } - } - } else { - bail!("no plugin installed"); - } - - Ok(plugins) + }).collect() + }) + .map_err(|e| e.into()) } }