diff --git a/.github/workflows/reusable-sign-agent.yml b/.github/workflows/reusable-sign-agent.yml new file mode 100644 index 000000000..d8bc7315f --- /dev/null +++ b/.github/workflows/reusable-sign-agent.yml @@ -0,0 +1,289 @@ +name: "Reusable: Sign Agent Binaries" + +on: + workflow_call: + inputs: + os: + required: true + type: string + description: "Target OS to sign for: 'windows' or 'macos'" + artifact_name: + required: true + type: string + description: "Name of the artifact (uploaded by a previous job) that contains the unsigned binaries" + binaries: + required: true + type: string + description: | + Newline-separated list of binary paths to sign, relative to the root of the downloaded artifact. + Example: + agent/utmstack_agent_service_windows_amd64.exe + agent/updater/utmstack_updater_service_windows_amd64.exe + signed_artifact_name: + required: false + type: string + default: "" + description: "Name for the output artifact (defaults to -signed)" + retention_days: + required: false + type: number + default: 1 + + # ---- Windows / GCP KMS (used only when os=windows) ---- + gcp_project_id: + required: false + type: string + default: "" + kms_location: + required: false + type: string + default: "global" + kms_keyring: + required: false + type: string + default: "" + kms_key: + required: false + type: string + default: "" + cert_chain_path: + required: false + type: string + default: ".github/certs/codesign-chain.pem" + description: "Path (in the repo) to the PEM cert chain used by jsign" + jsign_version: + required: false + type: string + default: "7.0" + sign_name: + required: false + type: string + default: "UTMStack Agent" + sign_url: + required: false + type: string + default: "https://utmstack.com" + tsa_url: + required: false + type: string + default: "http://timestamp.sectigo.com" + + secrets: + # Windows + GCP_WINDOWS_SIGNER_SA_KEY: + required: false + WINDOWS_SIGNER_CERT_CHAIN_PEM: + required: false + description: "Full PEM cert chain content. When set, overrides cert_chain_path." + # macOS + APPLE_CERTIFICATE_BASE64: + required: false + APPLE_CERTIFICATE_PASSWORD: + required: false + APPLE_SIGNING_IDENTITY: + required: false + APPLE_ID: + required: false + APPLE_APP_PASSWORD: + required: false + APPLE_TEAM_ID: + required: false + +jobs: + sign: + name: Sign ${{ inputs.os }} binaries + runs-on: ${{ inputs.os == 'windows' && 'ubuntu-latest' || 'macos-latest' }} + permissions: + contents: read + id-token: write + + steps: + - name: Checkout (for cert chain) + if: inputs.os == 'windows' + uses: actions/checkout@v4 + + - name: Download unsigned binaries + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact_name }} + path: ./unsigned + + # ========================================================= + # Windows path: jsign + GCP KMS + # ========================================================= + - name: Authenticate to Google Cloud + if: inputs.os == 'windows' + uses: google-github-actions/auth@v2 + with: + credentials_json: ${{ secrets.GCP_WINDOWS_SIGNER_SA_KEY }} + + - name: Set up gcloud + if: inputs.os == 'windows' + uses: google-github-actions/setup-gcloud@v2 + + - name: Set up Java (for jsign) + if: inputs.os == 'windows' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + + - name: Download jsign + if: inputs.os == 'windows' + env: + JSIGN_VERSION: ${{ inputs.jsign_version }} + run: | + curl -fsSL -o jsign.jar \ + "https://github.com/ebourg/jsign/releases/download/${JSIGN_VERSION}/jsign-${JSIGN_VERSION}.jar" + + - name: Prepare cert chain + if: inputs.os == 'windows' + env: + CHAIN_SECRET: ${{ secrets.WINDOWS_SIGNER_CERT_CHAIN_PEM }} + CHAIN_REPO_PATH: ${{ inputs.cert_chain_path }} + run: | + set -euo pipefail + OUT="${RUNNER_TEMP}/codesign-chain.pem" + if [ -n "$CHAIN_SECRET" ]; then + echo "→ Using cert chain from secret" + printf '%s\n' "$CHAIN_SECRET" > "$OUT" + elif [ -f "$CHAIN_REPO_PATH" ]; then + echo "→ Using cert chain from repo: $CHAIN_REPO_PATH" + cp "$CHAIN_REPO_PATH" "$OUT" + else + echo "::error::No cert chain available. Set WINDOWS_SIGNER_CERT_CHAIN_PEM secret or commit a chain at ${CHAIN_REPO_PATH}" + exit 1 + fi + echo "CERT_CHAIN_FILE=${OUT}" >> "$GITHUB_ENV" + + - name: Sign Windows binaries + if: inputs.os == 'windows' + env: + PROJECT_ID: ${{ inputs.gcp_project_id }} + KEYRING_LOCATION: ${{ inputs.kms_location }} + KEYRING_NAME: ${{ inputs.kms_keyring }} + KEY_NAME: ${{ inputs.kms_key }} + SIGN_NAME: ${{ inputs.sign_name }} + SIGN_URL: ${{ inputs.sign_url }} + TSA_URL: ${{ inputs.tsa_url }} + BINARIES: ${{ inputs.binaries }} + run: | + set -euo pipefail + + TOKEN=$(gcloud auth print-access-token) + KEYSTORE="projects/${PROJECT_ID}/locations/${KEYRING_LOCATION}/keyRings/${KEYRING_NAME}" + + while IFS= read -r raw; do + bin=$(echo "$raw" | xargs) + [ -z "$bin" ] && continue + target="./unsigned/${bin}" + echo "→ Signing ${target}" + ls -la "$target" + + java -jar jsign.jar \ + --storetype GOOGLECLOUD \ + --storepass "$TOKEN" \ + --keystore "$KEYSTORE" \ + --alias "$KEY_NAME" \ + --certfile "$CERT_CHAIN_FILE" \ + --tsaurl "$TSA_URL" \ + --tsmode RFC3161 \ + --name "$SIGN_NAME" \ + --url "$SIGN_URL" \ + "$target" + + echo "✓ Signed ${target}" + done <<< "$BINARIES" + + # ========================================================= + # macOS path: codesign + notarytool + # ========================================================= + - name: Install Apple certificate + if: inputs.os == 'macos' + env: + CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }} + CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + run: | + set -euo pipefail + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + KEYCHAIN_PASSWORD=$(openssl rand -base64 32) + + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + + echo "$CERTIFICATE_BASE64" | base64 --decode > "$RUNNER_TEMP/certificate.p12" + security import "$RUNNER_TEMP/certificate.p12" -P "$CERTIFICATE_PASSWORD" \ + -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" + security list-keychain -d user -s "$KEYCHAIN_PATH" + + security set-key-partition-list -S apple-tool:,apple:,codesign: \ + -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + + - name: Sign macOS binaries + if: inputs.os == 'macos' + env: + SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + BINARIES: ${{ inputs.binaries }} + run: | + set -euo pipefail + while IFS= read -r raw; do + bin=$(echo "$raw" | xargs) + [ -z "$bin" ] && continue + target="./unsigned/${bin}" + echo "→ Signing ${target}" + codesign --force --options runtime \ + --sign "$SIGNING_IDENTITY" \ + --timestamp \ + "$target" + done <<< "$BINARIES" + + - name: Notarize macOS binaries + if: inputs.os == 'macos' + env: + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + BINARIES: ${{ inputs.binaries }} + run: | + set -euo pipefail + while IFS= read -r raw; do + bin=$(echo "$raw" | xargs) + [ -z "$bin" ] && continue + target="./unsigned/${bin}" + zip_path="${target}.notarize.zip" + echo "→ Notarizing ${target}" + ( cd "$(dirname "$target")" && zip "$(basename "$target").notarize.zip" "$(basename "$target")" ) + + xcrun notarytool submit "$zip_path" \ + --apple-id "$APPLE_ID" \ + --password "$APPLE_APP_PASSWORD" \ + --team-id "$APPLE_TEAM_ID" \ + --wait + + rm -f "$zip_path" + echo "✓ Notarized ${target}" + done <<< "$BINARIES" + + # ========================================================= + # Upload signed binaries + # ========================================================= + - name: Compute signed artifact name + id: artifact + env: + OVERRIDE: ${{ inputs.signed_artifact_name }} + DEFAULT: ${{ inputs.artifact_name }}-signed + run: | + if [ -n "$OVERRIDE" ]; then + echo "name=$OVERRIDE" >> "$GITHUB_OUTPUT" + else + echo "name=$DEFAULT" >> "$GITHUB_OUTPUT" + fi + + - name: Upload signed binaries + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.artifact.outputs.name }} + path: ./unsigned/ + retention-days: ${{ inputs.retention_days }} + if-no-files-found: error diff --git a/.github/workflows/v11-deployment-pipeline.yml b/.github/workflows/v11-deployment-pipeline.yml index cf15b2677..de914a925 100644 --- a/.github/workflows/v11-deployment-pipeline.yml +++ b/.github/workflows/v11-deployment-pipeline.yml @@ -122,10 +122,10 @@ jobs: fi build_agent: - name: Build and Sign Agent + name: Build Agent Binaries needs: [setup_deployment] if: ${{ needs.setup_deployment.outputs.tag != '' }} - runs-on: utmstack-signer + runs-on: ubuntu-24.04 steps: - name: Check out code into the right branch uses: actions/checkout@v4 @@ -174,133 +174,83 @@ jobs: cd ${{ github.workspace }}/agent/updater go build -o utmstack_updater_service_windows_arm64.exe . - - name: Sign Windows Agents + - name: Build macOS Binaries (arm64) + env: + GOOS: darwin + GOARCH: arm64 + CGO_ENABLED: 0 run: | cd ${{ github.workspace }}/agent - signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 /f "${{ vars.SIGN_CERT }}" /csp "eToken Base Cryptographic Provider" /k "[{{${{ secrets.SIGN_KEY }}}}]=${{ secrets.SIGN_CONTAINER }}" "utmstack_agent_service_windows_amd64.exe" - signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 /f "${{ vars.SIGN_CERT }}" /csp "eToken Base Cryptographic Provider" /k "[{{${{ secrets.SIGN_KEY }}}}]=${{ secrets.SIGN_CONTAINER }}" "utmstack_agent_service_windows_arm64.exe" + go build -o utmstack_agent_service_darwin_arm64 -v -ldflags "-X 'github.com/utmstack/UTMStack/agent/config.REPLACE_KEY=${{ secrets.AGENT_SECRET_PREFIX }}'" . cd ${{ github.workspace }}/agent/updater - signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 /f "${{ vars.SIGN_CERT }}" /csp "eToken Base Cryptographic Provider" /k "[{{${{ secrets.SIGN_KEY }}}}]=${{ secrets.SIGN_CONTAINER }}" "utmstack_updater_service_windows_amd64.exe" - signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 /f "${{ vars.SIGN_CERT }}" /csp "eToken Base Cryptographic Provider" /k "[{{${{ secrets.SIGN_KEY }}}}]=${{ secrets.SIGN_CONTAINER }}" "utmstack_updater_service_windows_arm64.exe" + go build -o utmstack_updater_service_darwin_arm64 . - - name: Upload signed binaries as artifacts + - name: Upload Linux binaries as artifact uses: actions/upload-artifact@v4 with: - name: signed-agents + name: agents-linux path: | - ${{ github.workspace }}/agent/utmstack_agent_service_linux_amd64 - ${{ github.workspace }}/agent/utmstack_agent_service_linux_arm64 - ${{ github.workspace }}/agent/utmstack_agent_service_windows_amd64.exe - ${{ github.workspace }}/agent/utmstack_agent_service_windows_arm64.exe - ${{ github.workspace }}/agent/updater/utmstack_updater_service_linux_amd64 - ${{ github.workspace }}/agent/updater/utmstack_updater_service_linux_arm64 - ${{ github.workspace }}/agent/updater/utmstack_updater_service_windows_amd64.exe - ${{ github.workspace }}/agent/updater/utmstack_updater_service_windows_arm64.exe + agent/utmstack_agent_service_linux_amd64 + agent/utmstack_agent_service_linux_arm64 + agent/updater/utmstack_updater_service_linux_amd64 + agent/updater/utmstack_updater_service_linux_arm64 retention-days: 1 - build_agent_darwin: - name: Build and Sign Agent (macOS) - needs: [setup_deployment] - if: ${{ needs.setup_deployment.outputs.tag != '' }} - runs-on: macos-latest - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 + - name: Upload unsigned Windows binaries as artifact + uses: actions/upload-artifact@v4 with: - go-version: '1.23' - - - name: Install Apple Certificate - env: - CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }} - CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - run: | - # Create temporary keychain - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - KEYCHAIN_PASSWORD=$(openssl rand -base64 32) - - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - - # Import certificate - echo "$CERTIFICATE_BASE64" | base64 --decode > $RUNNER_TEMP/certificate.p12 - security import $RUNNER_TEMP/certificate.p12 -P "$CERTIFICATE_PASSWORD" \ - -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH - - # Allow codesign without prompt - security set-key-partition-list -S apple-tool:,apple:,codesign: \ - -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - - - name: Build macOS Agent (arm64) - env: - GOOS: darwin - GOARCH: arm64 - CGO_ENABLED: 0 - run: | - cd ${{ github.workspace }}/agent - go build -o utmstack_agent_service_darwin_arm64 -v \ - -ldflags "-X 'github.com/utmstack/UTMStack/agent/config.REPLACE_KEY=${{ secrets.AGENT_SECRET_PREFIX }}'" . - - cd ${{ github.workspace }}/agent/updater - go build -o utmstack_updater_service_darwin_arm64 . - - - name: Sign macOS Binaries - env: - SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} - run: | - # Sign agent - codesign --force --options runtime \ - --sign "$SIGNING_IDENTITY" \ - --timestamp \ - ${{ github.workspace }}/agent/utmstack_agent_service_darwin_arm64 - - # Sign updater - codesign --force --options runtime \ - --sign "$SIGNING_IDENTITY" \ - --timestamp \ - ${{ github.workspace }}/agent/updater/utmstack_updater_service_darwin_arm64 - - - name: Notarize macOS Binaries - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - run: | - # Create zip for notarization (notarytool requires zip/pkg/dmg) - cd ${{ github.workspace }}/agent - zip utmstack_agent_darwin_arm64.zip utmstack_agent_service_darwin_arm64 + name: agents-windows-unsigned + path: | + agent/utmstack_agent_service_windows_amd64.exe + agent/utmstack_agent_service_windows_arm64.exe + agent/updater/utmstack_updater_service_windows_amd64.exe + agent/updater/utmstack_updater_service_windows_arm64.exe + retention-days: 1 - cd ${{ github.workspace }}/agent/updater - zip utmstack_updater_darwin_arm64.zip utmstack_updater_service_darwin_arm64 - - # Notarize agent - xcrun notarytool submit ${{ github.workspace }}/agent/utmstack_agent_darwin_arm64.zip \ - --apple-id "$APPLE_ID" \ - --password "$APPLE_APP_PASSWORD" \ - --team-id "$APPLE_TEAM_ID" \ - --wait - - # Notarize updater - xcrun notarytool submit ${{ github.workspace }}/agent/updater/utmstack_updater_darwin_arm64.zip \ - --apple-id "$APPLE_ID" \ - --password "$APPLE_APP_PASSWORD" \ - --team-id "$APPLE_TEAM_ID" \ - --wait - - - name: Upload macOS binaries as artifacts + - name: Upload unsigned macOS binaries as artifact uses: actions/upload-artifact@v4 with: - name: signed-agents-darwin + name: agents-darwin-unsigned path: | - ${{ github.workspace }}/agent/utmstack_agent_service_darwin_arm64 - ${{ github.workspace }}/agent/updater/utmstack_updater_service_darwin_arm64 + agent/utmstack_agent_service_darwin_arm64 + agent/updater/utmstack_updater_service_darwin_arm64 retention-days: 1 + sign_agent_windows: + name: Sign Windows Agent Binaries + needs: [build_agent, setup_deployment] + if: ${{ needs.setup_deployment.outputs.tag != '' }} + uses: ./.github/workflows/reusable-sign-agent.yml + with: + os: windows + artifact_name: agents-windows-unsigned + signed_artifact_name: agents-windows-signed + gcp_project_id: ${{ vars.GCP_PROJECT_PROD }} + kms_location: ${{ vars.KMS_KEYRING_LOCATION }} + kms_keyring: ${{ vars.KMS_KEYRING_NAME }} + kms_key: ${{ vars.KMS_KEY_NAME }} + binaries: | + utmstack_agent_service_windows_amd64.exe + utmstack_agent_service_windows_arm64.exe + updater/utmstack_updater_service_windows_amd64.exe + updater/utmstack_updater_service_windows_arm64.exe + secrets: inherit + + sign_agent_macos: + name: Sign macOS Agent Binaries + needs: [build_agent, setup_deployment] + if: ${{ needs.setup_deployment.outputs.tag != '' }} + uses: ./.github/workflows/reusable-sign-agent.yml + with: + os: macos + artifact_name: agents-darwin-unsigned + signed_artifact_name: agents-darwin-signed + binaries: | + utmstack_agent_service_darwin_arm64 + updater/utmstack_updater_service_darwin_arm64 + secrets: inherit + build_utmstack_collector: name: Build UTMStack Collector needs: [setup_deployment] @@ -337,17 +287,23 @@ jobs: build_agent_manager: name: Build Agent Manager Microservice - needs: [build_agent, build_agent_darwin, build_utmstack_collector, setup_deployment] - if: ${{ always() && needs.build_agent.result == 'success' && needs.build_agent_darwin.result == 'success' && needs.build_utmstack_collector.result == 'success' && needs.setup_deployment.outputs.tag != '' }} + needs: [sign_agent_windows, sign_agent_macos, build_utmstack_collector, setup_deployment] + if: ${{ always() && needs.sign_agent_windows.result == 'success' && needs.sign_agent_macos.result == 'success' && needs.build_utmstack_collector.result == 'success' && needs.setup_deployment.outputs.tag != '' }} runs-on: ubuntu-24.04 steps: - name: Check out code into the right branch uses: actions/checkout@v4 - - name: Download signed agents from artifacts + - name: Download Linux agents from artifact uses: actions/download-artifact@v4 with: - name: signed-agents + name: agents-linux + path: ${{ github.workspace }}/agent + + - name: Download signed Windows agents from artifact + uses: actions/download-artifact@v4 + with: + name: agents-windows-signed path: ${{ github.workspace }}/agent - name: Download UTMStack Collectors from artifacts @@ -356,10 +312,10 @@ jobs: name: utmstack-collectors path: ${{ github.workspace }}/utmstack-collector - - name: Download signed macOS agents from artifacts + - name: Download signed macOS agents from artifact uses: actions/download-artifact@v4 with: - name: signed-agents-darwin + name: agents-darwin-signed path: ${{ github.workspace }}/agent-darwin - name: Prepare dependencies for Agent Manager Image @@ -407,7 +363,7 @@ jobs: cp "${{ github.workspace }}/agent/updater/utmstack_updater_service_windows_arm64.exe" ./dependencies/agent/utmstack_updater_service_arm64.exe cp "${{ github.workspace }}/agent/version.json" ./dependencies/agent/ - + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -422,7 +378,7 @@ jobs: push: true provenance: false tags: ghcr.io/utmstack/utmstack/agent-manager:${{ needs.setup_deployment.outputs.tag }} - + build_event_processor: name: Build Event Processor Microservice needs: [setup_deployment] @@ -494,7 +450,6 @@ jobs: maven_profile: 'prod' maven_goals: 'clean package' copy_filters_and_rules: true - build_frontend: name: Build Frontend Microservice needs: [validations, setup_deployment] @@ -503,7 +458,7 @@ jobs: with: image_name: frontend tag: ${{ needs.setup_deployment.outputs.tag }} - + build_user_auditor: name: Build User-Auditor Microservice needs: [validations, setup_deployment] @@ -515,7 +470,7 @@ jobs: java_version: '11' use_version_file: false maven_goals: 'clean install -U' - + build_web_pdf: name: Build Web-PDF Microservice needs: [validations, setup_deployment] @@ -692,4 +647,4 @@ jobs: done echo "✅ Scheduled release for all instances with version $TAG" - \ No newline at end of file + diff --git a/agent/dependency/dependency.go b/agent/dependency/dependency.go index 6070fa23c..7d459a772 100644 --- a/agent/dependency/dependency.go +++ b/agent/dependency/dependency.go @@ -60,17 +60,17 @@ func UpdaterFile(suffix string) string { // Dependency represents a dependency that the agent needs. type Dependency struct { - Name string // Unique identifier - Version string // Current version in this agent build - BinaryPath string // Path to check if already exists - DownloadURL func(server string) string // URL template to download from - DownloadName string // Filename to save as (if different from BinaryPath basename) - Critical bool // If true, failure blocks agent startup + Name string // Unique identifier + Version string // Current version in this agent build + BinaryPath string // Path to check if already exists + DownloadURL func(server string) string // URL template to download from + DownloadName string // Filename to save as (if different from BinaryPath basename) + Critical bool // If true, failure blocks agent startup PreDownload func() (cleanup func(), err error) // Called before download, returns cleanup for rollback - PostDownload func() error // Run after download (e.g., unzip). Can be nil. - Configure func() error // Run on first install (can be nil) - Update func() error // Run on version change (can be nil, uses Configure) - Uninstall func() error // Run when dependency is removed (can be nil) + PostDownload func() error // Run after download (e.g., unzip). Can be nil. + Configure func() error // Run on first install (can be nil) + Update func() error // Run on version change (can be nil, uses Configure) + Uninstall func() error // Run when dependency is removed (can be nil) } // Exists checks if the dependency binary exists on disk. @@ -212,7 +212,7 @@ func Reconcile(server string, skipCertValidation bool) error { } else if inst.Version != dep.Version { // VERSION CHANGED: Download (if needed) and update utils.Logger.Info("Updating dependency: %s (%s -> %s)", dep.Name, inst.Version, dep.Version) - + // Call PreDownload hook if defined var cleanup func() if dep.PreDownload != nil { diff --git a/agent/dependency/deps_linux_arm64.go b/agent/dependency/deps_linux_arm64.go index 384d10f1e..9ad094659 100644 --- a/agent/dependency/deps_linux_arm64.go +++ b/agent/dependency/deps_linux_arm64.go @@ -43,6 +43,18 @@ func GetDependencies() []Dependency { Update: updateAuditdRules, Uninstall: cleanupAuditd, }, + + // Auditd dependency - auto-configures Linux audit daemon + // No download - installs from system package manager + { + Name: "auditd", + Version: AuditdVersion, + BinaryPath: "/sbin/auditctl", // Check if auditd tools exist + Critical: false, + Configure: configureAuditd, + Update: updateAuditdRules, + Uninstall: cleanupAuditd, + }, } } diff --git a/agent/version.json b/agent/version.json index b60b61712..8981e0f87 100644 --- a/agent/version.json +++ b/agent/version.json @@ -1,4 +1,4 @@ { - "version": "11.1.4", + "version": "11.1.5", "updater_version": "1.0.4" } diff --git a/backend/src/main/java/com/park/utmstack/domain/application_modules/validators/UtmModuleConfigValidator.java b/backend/src/main/java/com/park/utmstack/domain/application_modules/validators/UtmModuleConfigValidator.java index 09fd01758..dc05b27f3 100644 --- a/backend/src/main/java/com/park/utmstack/domain/application_modules/validators/UtmModuleConfigValidator.java +++ b/backend/src/main/java/com/park/utmstack/domain/application_modules/validators/UtmModuleConfigValidator.java @@ -40,10 +40,10 @@ public boolean validate(UtmModule module, List keys // User provided a new value — use it as plaintext value = override.getConfValue(); } else { - // No override or masked — decrypt from DB - value = decryptIfNeeded(dbConf.getConfDataType(), dbConf.getConfValue()); + // No override or masked + value = dbConf.getConfValue(); } - return new UtmModuleGroupConfDTO(dbConf.getConfKey(), value); + return new UtmModuleGroupConfDTO(dbConf.getConfDataType(),dbConf.getConfKey(), value); }) .toList(); @@ -59,10 +59,4 @@ private UtmModuleGroupConfiguration findInKeys(List .orElse(null); } - private String decryptIfNeeded(String dataType, String value) { - if (Constants.CONF_TYPE_PASSWORD.equals(dataType) || Constants.CONF_TYPE_FILE.equals(dataType)) { - return CipherUtil.decrypt(value, System.getenv(Constants.ENV_ENCRYPTION_KEY)); - } - return value; - } } diff --git a/backend/src/main/java/com/park/utmstack/event_processor/EventProcessorManagerService.java b/backend/src/main/java/com/park/utmstack/event_processor/EventProcessorManagerService.java index 96c3b51d7..4c95d489c 100644 --- a/backend/src/main/java/com/park/utmstack/event_processor/EventProcessorManagerService.java +++ b/backend/src/main/java/com/park/utmstack/event_processor/EventProcessorManagerService.java @@ -1,13 +1,8 @@ package com.park.utmstack.event_processor; import com.park.utmstack.config.Constants; -import com.park.utmstack.domain.application_modules.UtmModule; -import com.park.utmstack.domain.application_modules.UtmModuleGroup; -import com.park.utmstack.domain.application_modules.enums.ModuleName; import com.park.utmstack.service.dto.application_modules.ModuleDTO; -import com.park.utmstack.service.dto.application_modules.UtmModuleMapper; import com.park.utmstack.service.web_clients.rest_template.RestTemplateService; -import com.park.utmstack.util.CipherUtil; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,11 +10,9 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; import org.springframework.web.util.UriComponentsBuilder; import java.util.List; -import java.util.Set; @Service @RequiredArgsConstructor @@ -30,8 +23,6 @@ public class EventProcessorManagerService { private final RestTemplateService restTemplateService; - private final List typeFileNeedsDecryptList = List.of(ModuleName.GCP); - public static final String EVENT_PROCESSOR_BASE_URL = "http://" + System.getenv(Constants.ENV_EVENT_PROCESSOR_HOST) + ":" + System.getenv(Constants.ENV_EVENT_PROCESSOR_PORT); @@ -45,7 +36,6 @@ public void updateModule(ModuleDTO module) { .toUriString(); try{ - this.decryptModuleConfig (module); ResponseEntity response = restTemplateService.post( url, List.of(module), @@ -60,27 +50,6 @@ public void updateModule(ModuleDTO module) { } } - public void decryptModuleConfig (UtmModule module){ - Set groups = module.getModuleGroups(); - decryptModuleGroupsConfig(groups, module.getModuleName()); - } - - public void decryptModuleConfig (ModuleDTO moduleDTO){ - Set groups = moduleDTO.getModuleGroups(); - decryptModuleGroupsConfig(groups, moduleDTO.getModuleName()); - } - - private void decryptModuleGroupsConfig(Set groups, ModuleName moduleName) { - groups.forEach((gp) -> { - gp.getModuleGroupConfigurations().forEach((gpc) -> { - if ((gpc.getConfDataType().equals(Constants.CONF_TYPE_PASSWORD) && StringUtils.hasText(gpc.getConfValue())) - || (gpc.getConfDataType().equals(Constants.CONF_TYPE_FILE) && StringUtils.hasText(gpc.getConfValue())) && typeFileNeedsDecryptList.contains(moduleName)) { - gpc.setConfValue(CipherUtil.decrypt(gpc.getConfValue(), System.getenv(Constants.ENV_ENCRYPTION_KEY))); - } - }); - }); - } - private HttpHeaders buildEventProcessorHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); diff --git a/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupConfigurationService.java b/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupConfigurationService.java index a0231e944..3c6ecec19 100644 --- a/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupConfigurationService.java +++ b/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupConfigurationService.java @@ -43,6 +43,11 @@ public void createConfigurationKeys(List keys) thro try { if (CollectionUtils.isEmpty(keys)) return; + for (UtmModuleGroupConfiguration key : keys) { + if (isSensitiveType(key.getConfDataType()) && StringUtils.hasText(key.getConfValue())) { + key.setConfValue(CipherUtil.encrypt(key.getConfValue(), System.getenv(Constants.ENV_ENCRYPTION_KEY))); + } + } moduleConfigurationRepository.saveAll(keys); } catch (Exception e) { throw new Exception(ctx + ": " + e.getMessage()); @@ -105,6 +110,7 @@ public UtmModule updateConfigurationKeys(Long moduleId, List findAllByGroupId(Long groupId) throws Exception { final String ctx = CLASSNAME + ".findAllByGroupId"; try { @@ -119,6 +125,7 @@ public List findAllByGroupId(Long groupId) throws E /** * Gets all configuration parameter for a group and convert it to a map */ + @Transactional(readOnly = true) public Map getGroupConfigurationAsMap(Long groupId) throws Exception { final String ctx = CLASSNAME + ".getGroupConfigurationAsMap"; try { @@ -136,6 +143,7 @@ public Map getGroupConfigurationAsMap(Long groupId) throws Excep /** * Find a configuration parameter by his group and key */ + @Transactional(readOnly = true) public UtmModuleGroupConfiguration findByGroupIdAndConfKey(Long groupId, String confKey) throws Exception { final String ctx = CLASSNAME + ".findByGroupIdAndConfKey"; try { diff --git a/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupService.java b/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupService.java index 750898f30..4daa5bed9 100644 --- a/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupService.java +++ b/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleGroupService.java @@ -249,13 +249,19 @@ public void updateCollectorConfigurationKeys(CollectorConfigDTO collectorConfig) moduleGroupRepository.deleteAll(dbConfigs); } else { for (UtmModuleGroupConfiguration key : keys) { - if (key.getConfDataType().equals("password")) { - if (Constants.MASKED_VALUE.equals(key.getConfValue())) { - continue; - } + boolean isSensitive = isSensitiveType(key.getConfDataType()); + if (isSensitive && Constants.MASKED_VALUE.equals(key.getConfValue())) { + continue; + } + if (isSensitive) { key.setConfValue(CipherUtil.encrypt(key.getConfValue(), System.getenv(Constants.ENV_ENCRYPTION_KEY))); } } + + List toSave = keys.stream() + .filter(k -> !(isSensitiveType(k.getConfDataType()) && Constants.MASKED_VALUE.equals(k.getConfValue()))) + .collect(Collectors.toList()); + List keyGroupIds = keys.stream() .map(UtmModuleGroupConfiguration::getGroupId) .toList(); @@ -265,7 +271,9 @@ public void updateCollectorConfigurationKeys(CollectorConfigDTO collectorConfig) .collect(Collectors.toList()); moduleGroupRepository.deleteAll(groupsToDelete); - moduleGroupConfigurationRepository.saveAll(keys); + if (!toSave.isEmpty()) { + moduleGroupConfigurationRepository.saveAll(toSave); + } } } catch (Exception e) { @@ -274,4 +282,8 @@ public void updateCollectorConfigurationKeys(CollectorConfigDTO collectorConfig) } } + private boolean isSensitiveType(String dataType) { + return Constants.CONF_TYPE_PASSWORD.equals(dataType) || Constants.CONF_TYPE_FILE.equals(dataType); + } + } diff --git a/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleService.java b/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleService.java index a594db273..dc6ef6ac4 100644 --- a/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleService.java +++ b/backend/src/main/java/com/park/utmstack/service/application_modules/UtmModuleService.java @@ -62,9 +62,7 @@ public UtmModule activateDeactivate(ModuleActivationDTO moduleActivationDTO) { module.setModuleActive(activationStatus); module = moduleRepository.save(module); - List nonRemovableConf = List.of(ModuleName.SOC_AI); - - if (!activationStatus && !nonRemovableConf.contains(nameShort)) + if (!activationStatus) moduleGroupRepository.deleteAllByModuleId(module.getId()); enableDisableModuleMenus(nameShort, activationStatus); diff --git a/backend/src/main/java/com/park/utmstack/service/dto/application_modules/UtmModuleGroupConfDTO.java b/backend/src/main/java/com/park/utmstack/service/dto/application_modules/UtmModuleGroupConfDTO.java index 1a4b88ba3..349d51563 100644 --- a/backend/src/main/java/com/park/utmstack/service/dto/application_modules/UtmModuleGroupConfDTO.java +++ b/backend/src/main/java/com/park/utmstack/service/dto/application_modules/UtmModuleGroupConfDTO.java @@ -9,6 +9,7 @@ @NoArgsConstructor @AllArgsConstructor public class UtmModuleGroupConfDTO { + private String confDataType; private String confKey; private String confValue; } diff --git a/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleGroupResource.java b/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleGroupResource.java index 3c7e179df..1b420fbec 100644 --- a/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleGroupResource.java +++ b/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleGroupResource.java @@ -159,6 +159,17 @@ public ResponseEntity getConfigurationGroup(@PathVariable Long g final String ctx = CLASSNAME + ".getConfigurationGroups"; Optional group = moduleGroupService.findOne(groupId); + group.ifPresent(g -> { + if (g.getModuleGroupConfigurations() != null) { + for (UtmModuleGroupConfiguration conf : g.getModuleGroupConfigurations()) { + if ((Constants.CONF_TYPE_PASSWORD.equals(conf.getConfDataType()) + || Constants.CONF_TYPE_FILE.equals(conf.getConfDataType())) + && conf.getConfValue() != null) { + conf.setConfValue(Constants.MASKED_VALUE); + } + } + } + }); return ResponseUtil.wrapOrNotFound(group); } diff --git a/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleResource.java b/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleResource.java index 1fe1ef8ae..db36960c9 100644 --- a/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleResource.java +++ b/backend/src/main/java/com/park/utmstack/web/rest/application_modules/UtmModuleResource.java @@ -124,9 +124,7 @@ public ResponseEntity getModuleDetailsDecrypted(@RequestParam ModuleN final String ctx = CLASSNAME + ".getModuleDetailsDecrypted"; try { UtmModule module = moduleFactory.getInstance(nameShort).getDetails(utmServerRepository.getUtmServer()); - if (InternalApiKeyFilter.isApiKeyHeaderInUse()) { - this.eventProcessorManagerService.decryptModuleConfig(module); - } else { + if (!InternalApiKeyFilter.isApiKeyHeaderInUse()) { String msg = ctx + ": You must provide the header used to communicate internally with this resource"; log.error(msg); eventService.createEvent(msg, ApplicationEventType.ERROR); diff --git a/frontend/src/app/app-module/guides/guide-cisco/guide-cisco.component.ts b/frontend/src/app/app-module/guides/guide-cisco/guide-cisco.component.ts index f6e11a46f..a72837b6a 100644 --- a/frontend/src/app/app-module/guides/guide-cisco/guide-cisco.component.ts +++ b/frontend/src/app/app-module/guides/guide-cisco/guide-cisco.component.ts @@ -14,7 +14,7 @@ export class GuideCiscoComponent implements OnInit { @Input() serverId: number; ciscoPaths: CiscoOSPaths[] = [ - {os: 'linux', path: '/opt/utmstack-linux-agent/log-collector-config.json'}, + {os: 'linux', path: '/opt/utmstack_agent_service_linux_amd64/log-collector-config.json'}, {os: 'windows', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\log-collector-config.json'} ]; ciscoPorts: CiscoPorts[] = [ diff --git a/frontend/src/app/app-module/guides/guide-filebeat-generic/guide-filebeat-generic.component.ts b/frontend/src/app/app-module/guides/guide-filebeat-generic/guide-filebeat-generic.component.ts index b80f89611..88c0c7cf5 100644 --- a/frontend/src/app/app-module/guides/guide-filebeat-generic/guide-filebeat-generic.component.ts +++ b/frontend/src/app/app-module/guides/guide-filebeat-generic/guide-filebeat-generic.component.ts @@ -28,103 +28,103 @@ export class GuideFilebeatGenericComponent implements OnInit { }, ]; commandsActivate: FilebeatCommands[] = [ - {module: UtmModulesEnum.TRAEFIK, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.TRAEFIK, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable traefik', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.TRAEFIK, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable traefik', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.APACHE, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ./filebeat modules enable apache', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + {module: UtmModulesEnum.APACHE, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ./filebeat modules enable apache', + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.APACHE, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable apache', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.ELASTICSEARCH, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.ELASTICSEARCH, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable elasticsearch', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.ELASTICSEARCH, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable elasticsearch', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.HAPROXY, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.HAPROXY, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable haproxy', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.HAPROXY, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable haproxy', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.MONGODB, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.MONGODB, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable mongodb', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.MONGODB, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable mongodb', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.KIBANA, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.KIBANA, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable kibana', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.KIBANA, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable kibana', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.LOGSTASH, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.LOGSTASH, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable logstash', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.LOGSTASH, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable logstash', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.KAFKA, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.KAFKA, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable kafka', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.KAFKA, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable kafka', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.MYSQL, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.MYSQL, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable mysql', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.MYSQL, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable mysql', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.REDIS, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.REDIS, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable redis', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.REDIS, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable redis', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.POSTGRESQL, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.POSTGRESQL, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable postgresql', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.POSTGRESQL, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable postgresql', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.NGINX, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.NGINX, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable nginx', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.NGINX, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable nginx', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.AUDITD, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.AUDITD, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable auditd', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.OSQUERY, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.OSQUERY, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable osquery', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.OSQUERY, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable osquery', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, - {module: UtmModulesEnum.NATS, os: 'linux', command: 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ' + {module: UtmModulesEnum.NATS, os: 'linux', command: 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ' + './filebeat modules enable nats', - path: '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, + path: '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', restartCmd: 'sudo systemctl restart UTMStackModulesLogsCollector'}, {module: UtmModulesEnum.NATS, os: 'windows', command: 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\" ' + '&& filebeat modules enable nats', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', restartCmd: 'sc stop UTMStackModulesLogsCollector && timeout /t 5 && sc start UTMStackModulesLogsCollector'}, diff --git a/frontend/src/app/app-module/guides/guide-filebeat/guide-filebeat.component.html b/frontend/src/app/app-module/guides/guide-filebeat/guide-filebeat.component.html index 3a3253264..d0996ac1a 100644 --- a/frontend/src/app/app-module/guides/guide-filebeat/guide-filebeat.component.html +++ b/frontend/src/app/app-module/guides/guide-filebeat/guide-filebeat.component.html @@ -58,7 +58,7 @@

linux + code="/opt/utmstack_agent_service_linux_amd64/log-collector-config.json">
windows diff --git a/frontend/src/app/app-module/guides/guide-linux-agent/guide-linux-agent.component.ts b/frontend/src/app/app-module/guides/guide-linux-agent/guide-linux-agent.component.ts index 949b26fd3..9d3caeacd 100644 --- a/frontend/src/app/app-module/guides/guide-linux-agent/guide-linux-agent.component.ts +++ b/frontend/src/app/app-module/guides/guide-linux-agent/guide-linux-agent.component.ts @@ -35,42 +35,42 @@ export class GuideLinuxAgentComponent implements OnInit { getCommandUbuntu(installerName: string): string { const ip = window.location.host.includes(':') ? window.location.host.split(':')[0] : window.location.host; - return `sudo bash -c "apt update -y && apt install wget -y && mkdir -p /opt/utmstack-linux-agent && \ - wget --no-check-certificate -P /opt/utmstack-linux-agent \ + return `sudo bash -c "apt update -y && apt install wget -y && mkdir -p /opt/utmstack_agent_service_linux_amd64 && \ + wget --no-check-certificate -P /opt/utmstack_agent_service_linux_amd64 \ https://${ip}:9001/private/dependencies/agent/${installerName} && \ - chmod -R 755 /opt/utmstack-linux-agent/${installerName} && \ - /opt/utmstack-linux-agent/${installerName} install ${ip} ${this.token} yes"`; + chmod -R 755 /opt/utmstack_agent_service_linux_amd64/${installerName} && \ + /opt/utmstack_agent_service_linux_amd64/${installerName} install ${ip} ${this.token} yes"`; } getCommandCentos7RedHat(installerName: string): string { const ip = window.location.host.includes(':') ? window.location.host.split(':')[0] : window.location.host; - return `sudo bash -c "yum install wget -y && mkdir -p /opt/utmstack-linux-agent && \ - wget --no-check-certificate -P /opt/utmstack-linux-agent \ + return `sudo bash -c "yum install wget -y && mkdir -p /opt/utmstack_agent_service_linux_amd64 && \ + wget --no-check-certificate -P /opt/utmstack_agent_service_linux_amd64 \ https://${ip}:9001/private/dependencies/agent/${installerName} && \ - chmod -R 755 /opt/utmstack-linux-agent/${installerName} && \ - /opt/utmstack-linux-agent/${installerName} install ${ip} ${this.token} yes"`; + chmod -R 755 /opt/utmstack_agent_service_linux_amd64/${installerName} && \ + /opt/utmstack_agent_service_linux_amd64/${installerName} install ${ip} ${this.token} yes"`; } getCommandCentos8Almalinux(installerName: string): string { const ip = window.location.host.includes(':') ? window.location.host.split(':')[0] : window.location.host; - return `sudo bash -c "dnf install wget -y && mkdir -p /opt/utmstack-linux-agent && \ - wget --no-check-certificate -P /opt/utmstack-linux-agent \ + return `sudo bash -c "dnf install wget -y && mkdir -p /opt/utmstack_agent_service_linux_amd64 && \ + wget --no-check-certificate -P /opt/utmstack_agent_service_linux_amd64 \ https://${ip}:9001/private/dependencies/agent/${installerName} && \ - chmod -R 755 /opt/utmstack-linux-agent/${installerName} && \ - /opt/utmstack-linux-agent/${installerName} install ${ip} ${this.token} yes"`; + chmod -R 755 /opt/utmstack_agent_service_linux_amd64/${installerName} && \ + /opt/utmstack_agent_service_linux_amd64/${installerName} install ${ip} ${this.token} yes"`; } getUninstallCommand(installerName: string): string { - return `sudo bash -c "/opt/utmstack-linux-agent/${installerName} uninstall || true; \ + return `sudo bash -c "/opt/utmstack_agent_service_linux_amd64/${installerName} uninstall || true; \ systemctl stop UTMStackAgent 2>/dev/null || true; systemctl disable UTMStackAgent 2>/dev/null || true; \ rm -f /etc/systemd/system/UTMStackAgent.service 2>/dev/null || true; \ systemctl stop UTMStackModulesLogsCollector 2>/dev/null || true; \ systemctl disable UTMStackModulesLogsCollector 2>/dev/null || true; \ rm -f /etc/systemd/system/UTMStackModulesLogsCollector.service 2>/dev/null || true; \ systemctl daemon-reload 2>/dev/null || true; \ - echo 'Removing UTMStack Agent dependencies...' && sleep 10 && rm -rf /opt/utmstack-linux-agent 2>/dev/null || true; \ + echo 'Removing UTMStack Agent dependencies...' && sleep 10 && rm -rf /opt/utmstack_agent_service_linux_amd64 2>/dev/null || true; \ echo 'UTMStack Agent dependencies removed successfully.'"`; } diff --git a/frontend/src/app/app-module/guides/guide-netflow/guide-netflow.component.ts b/frontend/src/app/app-module/guides/guide-netflow/guide-netflow.component.ts index 38c86db99..299ae9c6f 100644 --- a/frontend/src/app/app-module/guides/guide-netflow/guide-netflow.component.ts +++ b/frontend/src/app/app-module/guides/guide-netflow/guide-netflow.component.ts @@ -12,7 +12,7 @@ export class GuideNetflowComponent implements OnInit { module = UtmModulesEnum; netflowPaths: NetflowOSPaths[] = [ - {os: 'linux', path: '/opt/utmstack-linux-agent/log-collector-config.json'}, + {os: 'linux', path: '/opt/utmstack_agent_service_linux_amd64/log-collector-config.json'}, {os: 'windows', path: 'C:\\Program Files\\UTMStack\\UTMStack Agent\\log-collector-config.json'} ]; constructor() { diff --git a/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.html b/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.html index 35ae48c9e..7c8c18c08 100644 --- a/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.html +++ b/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.html @@ -17,7 +17,7 @@

SOC AI

- + diff --git a/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.ts b/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.ts index 7d6e28aea..aba4d8fda 100644 --- a/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.ts +++ b/frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.ts @@ -308,7 +308,7 @@ export class GuideSocAiComponent implements OnInit { this.providerFormCache[this.activeProvider] = { values: {...this.formValues}, customModel: this.customModelValue, - headers: [...this.headerRows.map(r => ({...r}))] + headers: Array.from(this.headerRows.map(r => ({...r}))) }; } this.loading = false; diff --git a/frontend/src/app/app-module/guides/shared/constant.ts b/frontend/src/app/app-module/guides/shared/constant.ts index 5a0a93036..9fbe5b8a8 100644 --- a/frontend/src/app/app-module/guides/shared/constant.ts +++ b/frontend/src/app/app-module/guides/shared/constant.ts @@ -69,7 +69,7 @@ export const createPlatforms = ( linuxPath, linuxRestart, [ - `sudo bash -c "/opt/utmstack-linux-agent/utmstack_agent_service load-tls-certs [YOUR_CERT_PATH] [YOUR_KEY_PATH]"` + `sudo bash -c "/opt/utmstack_agent_service_linux_amd64/utmstack_agent_service load-tls-certs [YOUR_CERT_PATH] [YOUR_KEY_PATH]"` ] ), createPlatform( @@ -80,7 +80,7 @@ export const createPlatforms = ( linuxPath, linuxRestart, [ - `sudo bash -c "/opt/utmstack-linux-agent/utmstack_agent_service load-tls-certs [YOUR_CERT_PATH] [YOUR_KEY_PATH]"` + `sudo bash -c "/opt/utmstack_agent_service_linux_amd64/utmstack_agent_service load-tls-certs [YOUR_CERT_PATH] [YOUR_KEY_PATH]"` ] ) ] @@ -114,15 +114,15 @@ export const createFileBeatsPlatforms = ( export const PLATFORMS = createPlatforms( 'Start-Process "C:\\Program Files\\UTMStack\\UTMStack Agent\\utmstack_agent_service_windows_amd64.exe " -ArgumentList \'ACTION\', \'AGENT_NAME\', \'PROTOCOL\', \'TLS\' -NoNewWindow -Wait\n', 'Start-Process "C:\\Program Files\\UTMStack\\UTMStack Agent\\utmstack_agent_service_windows_arm64.exe" -ArgumentList \'ACTION\', \'AGENT_NAME\', \'PROTOCOL\, \'TLS\' -NoNewWindow -Wait\n', - 'sudo bash -c "/opt/utmstack-linux-agent/utmstack_agent_service_linux_amd64 ACTION AGENT_NAME PROTOCOL TLS"', - 'sudo bash -c "/opt/utmstack-linux-agent/utmstack_agent_service_linux_arm64 ACTION AGENT_NAME PROTOCOL TLS"' + 'sudo bash -c "/opt/utmstack_agent_service_linux_amd64/utmstack_agent_service_linux_amd64 ACTION AGENT_NAME PROTOCOL TLS"', + 'sudo bash -c "/opt/utmstack_agent_service_linux_amd64/utmstack_agent_service_linux_arm64 ACTION AGENT_NAME PROTOCOL TLS"' ); export const FILEBEAT_PLATFORMS = createFileBeatsPlatforms( 'cd "C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\"; Start-Process "filebeat.exe" -ArgumentList "modules", "enable", "AGENT_NAME"', - 'cd /opt/utmstack-linux-agent/beats/filebeat/ && ./filebeat modules enable AGENT_NAME', + 'cd /opt/utmstack_agent_service_linux_amd64/beats/filebeat/ && ./filebeat modules enable AGENT_NAME', 'C:\\Program Files\\UTMStack\\UTMStack Agent\\beats\\filebeat\\modules.d\\', 'Stop-Service -Name UTMStackModulesLogsCollector; Start-Sleep -Seconds 5; Start-Service -Name UTMStackModulesLogsCollector', - '/opt/utmstack-linux-agent/beats/filebeat/modules.d/', + '/opt/utmstack_agent_service_linux_amd64/beats/filebeat/modules.d/', 'sudo systemctl restart UTMStackModulesLogsCollector' ); diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html index bdf003915..47ed2747e 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html @@ -47,10 +47,22 @@
-
+
+
+ Error! + The SOC-AI integration could not analyze this alert due to a processing error. Please try again. +
+ +
+ +
Info! - The SOC-AI integration did not analyze this alert due to inactivity or a processing error. + This alert has not been analyzed by SOC-AI yet. You can start the analysis below.