u1timate
Published on 2024-11-04 / 30 Visits
0

elastic security本地化升级服务

0x01 本地化集成包更新服务

安装集成更新服务

容器

docker pull docker.elastic.co/package-registry/distribution:8.15.3

这个包很大, 建议使用🪜安装

  • 启动

docker run -it -p 8080:8080 docker.elastic.co/package-registry/distribution:8.15.3

使用该方式,每次有更新的时候,都需要重新拉取新包,比较麻烦, 后面会讲到使用程序进行自动更新

自编译

如果想要Kibana不去es官网而是从我们内网环境中获取集成组件的相关数据,就需要使用es官网提供的package-registry服务

相关源代码如下: https://github.com/elastic/package-registry

  • 基础环境准备

系统环境中需要安装golang, 目前的版本要求是1.23版本

wget https://go.dev/dl/go1.23.2.linux-amd64.tar.gz     
  • 编译更新服务

wget https://github.com/elastic/package-registry/archive/refs/tags/v1.26.0.zip 
unzip v1.26.0.zip 
cd  package-registry-1.26.0
go build
  • 修改配置文件config.yml

package_path参数根据具体环境指定即可,这里我将该路径指定为可执行程序的当前目录的packages目录下

package_paths:
  - ./packages

cache_time.index: 10s
cache_time.search: 10m
cache_time.categories: 10m
cache_time.catch_all: 10m
  • 启动服务

./package-registry --address 0.0.0.0:8080

同步集成包

  • 获取所有的集成包信息 https://epr.elastic.co/search

如果加上get参数all=truehttps://epr.elastic.co/search?all=true则表示获取所有的包。没有参数默认只返回最新的包。

返回格式如下:


[
    {
        "name": "1password",
        "title": "1Password",
        "version": "1.10.0",
        "release": "ga",
        "description": "Collect logs from 1Password with Elastic Agent.",
        "type": "integration",
        "download": "/epr/1password/1password-1.10.0.zip",
        "path": "/package/1password/1.10.0",
        "icons": [
            {
                "src": "/img/1password-logo-light-bg.svg",
                "path": "/package/1password/1.10.0/img/1password-logo-light-bg.svg",
                "title": "1Password",
                "size": "116x116",
                "type": "image/svg+xml"
            }
        ],
        "policy_templates": [
            {
                "name": "1password",
                "title": "1Password Events",
                "description": "Collect events from 1Password Events Reporting"
            }
        ],
        "conditions": {
            "kibana": {
                "version": "^8.6.1"
            }
        },
        "owner": {
            "github": "elastic/security-external-integrations"
        },
        "categories": [
            "security",
            "credential_management"
        ],
        "signature_path": "/epr/1password/1password-1.10.0.zip.sig"
    },
.....
]
  • 然后根据上面的返回的数据,从url https://package-storage.elastic.co/artifacts/packages/进行下载,比如下载1password,根据上面获取的数据中的signature_path字段,下载

# 下载安装包
https://package-storage.elastic.co/artifacts/packages/1password-1.10.0.zip

#下载hash
https://package-storage.elastic.co/artifacts/packages/1password-1.10.0.zip.sig
  • 实现自动化的集成更新程序。

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type UpdateIntegrations struct {
	installedIntegrations map[string]bool
	allIntegrations       map[string]bool
	interval              time.Duration
	directory             string
	newIntegrationsCount  int
}

func NewUpdateIntegrations(directory string, interval time.Duration) *UpdateIntegrations {
	return &UpdateIntegrations{
		installedIntegrations: make(map[string]bool),
		allIntegrations:       make(map[string]bool),
		interval:              interval,
		directory:             directory,
	}
}

var integrationClient = &http.Client{
	Transport: &http.Transport{DisableKeepAlives: false},
}

func (ui *UpdateIntegrations) getAllIntegrationsInfo() {
	log.Println("Getting all integrations info")
	client := &http.Client{}
	//"https://epr.elastic.co/search?all=true") # 获取所有的包
	req, err := http.NewRequest("GET", "https://epr.elastic.co/search", nil)
	if err != nil {
		log.Fatalf("Failed to create request: %v", err)
	}
	req.Header.Set("User-Agent", "Kibana/8.15.3 node-fetch")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("Failed to get response: %v", err)
	}
	defer resp.Body.Close()

	var items []map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
		log.Printf("Failed to decode JSON: %v", err)
	}

	for _, item := range items {
		if signaturePath, ok := item["signature_path"].(string); ok {
			filename := strings.TrimSuffix(filepath.Base(signaturePath), ".sig")
			ui.allIntegrations[filename] = true
		} else {
			log.Printf("Get signature_path error: %v", item["name"])
		}
	}
	log.Println("getAllIntegrationsInfo success")
}

func (ui *UpdateIntegrations) downloadFile(url, filename string) error {

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("User-Agent", "Kibana/8.15.3 node-fetch")

	resp, err := integrationClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to get response: %w", err)
	}
	defer resp.Body.Close()

	out, err := os.Create(filepath.Join(ui.directory, filename))
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer out.Close()

	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return fmt.Errorf("failed to write to file: %w", err)
	}

	return nil
}

func (ui *UpdateIntegrations) downloadIntegrations(filename string) {
	for i := 0; i < 3; i++ {
		if i > 0 {
			log.Printf("Download integrations failed, retry %d", i)
		}
		url := fmt.Sprintf("https://package-storage.elastic.co/artifacts/packages/%s", filename)
		if err := ui.downloadFile(url, filename); err != nil {
			log.Printf("Download integrations error: %v", err)
			time.Sleep(2 * time.Second)
			continue
		}

		sigFilename := filename + ".sig"
		sigURL := fmt.Sprintf("https://package-storage.elastic.co/artifacts/packages/%s", sigFilename)
		if err := ui.downloadFile(sigURL, sigFilename); err != nil {
			log.Printf("Download integrations sig file error: %v", err)
			time.Sleep(2 * time.Second)
			continue
		}

		ui.newIntegrationsCount++
		log.Printf("Download new integrations success: %s", filename)
		return
	}
}

func (ui *UpdateIntegrations) readPackagesName() {
	files, err := os.ReadDir(ui.directory)
	if err != nil {
		log.Fatalf("Failed to read directory: %v", err)
	}

	for _, file := range files {
		if strings.HasSuffix(file.Name(), ".sig") {
			ui.installedIntegrations[strings.TrimSuffix(file.Name(), ".sig")] = true
		}
	}
}

func (ui *UpdateIntegrations) updateIntegrations() {
	for {
		ui.getAllIntegrationsInfo()
		ui.readPackagesName()
		for filename := range ui.allIntegrations {
			if !ui.installedIntegrations[filename] {
				ui.downloadIntegrations(filename)
			}
		}
		log.Printf("updateIntegrations done, install new package number: %d", ui.newIntegrationsCount)
		log.Printf("sleep %f seconds", ui.interval.Seconds())
		ui.newIntegrationsCount = 0
		time.Sleep(ui.interval)
	}
}

func main() {
	logFile, err := os.OpenFile("./update_integrations.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Failed to open log file: %v", err)
	}
	defer logFile.Close()
	log.SetOutput(logFile)
	log.Println("update_integrations start")
	updateIntegrations := NewUpdateIntegrations("./packages", 24*time.Hour)
	updateIntegrations.updateIntegrations()
}

配置kibana

修改kibana的配置文件/etc/kibana/kibana.yml ,让其默认访问我们搭建的内网集成服务

xpack.fleet.isAirGapped: true
xpack.fleet.registryUrl: "http://127.0.0.1:8080"

重启kibana服务,完成

systemctl restart kibana

0x02 本地化二进制包升级服务

官网的地址为:https://artifacts.elastic.co

下载所有的二进制包

curl -O https://artifacts.elastic.co/downloads/apm-server/apm-server-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/apm-server/apm-server-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/apm-server/apm-server-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/auditbeat/auditbeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/osquerybeat/osquerybeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/osquerybeat/osquerybeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/osquerybeat/osquerybeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/beats/packetbeat/packetbeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/beats/packetbeat/packetbeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/beats/packetbeat/packetbeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/cloudbeat/cloudbeat-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/cloudbeat/cloudbeat-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/cloudbeat/cloudbeat-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/endpoint-dev/endpoint-security-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/endpoint-dev/endpoint-security-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/endpoint-dev/endpoint-security-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/fleet-server/fleet-server-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/fleet-server/fleet-server-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/fleet-server/fleet-server-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-host-agent-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-host-agent-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-host-agent-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-elastic-collector-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-elastic-collector-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-elastic-collector-8.15.3-linux-x86_64.tar.gz.asc
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-elastic-symbolizer-8.15.3-linux-x86_64.tar.gz
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-elastic-symbolizer-8.15.3-linux-x86_64.tar.gz.sha512
curl -O https://artifacts.elastic.co/downloads/prodfiler/pf-elastic-symbolizer-8.15.3-linux-x86_64.tar.gz.asc

然后自己搭建一个文件服务器即可完成。

注意: 访问的链接的格式必须满足 http[s]:/[你的域名或者IP+端口]/downloads/beats/osquerybeat/osquerybeat-8.15.3-linux-x86_64.tar.gz.sha512

最后在fleet-》设置 里面设置即可

参考

https://www.elastic.co/guide/en/fleet/8.15/air-gapped.html