---
# System prepended metadata

title: 安裝 Neuvector all-in-one (Docker、Podman)
tags: [工具]

---

# 安裝 Neuvector all-in-one (Docker、Podman)


## 安裝 NV
1. 須先安裝好 docker
2. 部署 allinone NV container
```
$ mkdir /var/neuvector

# CLUSTER_JOIN_ADDR 這是讓 enforce 或是 scanner 用來連接到的 IP 位址，通常是 allinone NV 本機 IP
$ docker run -d --name allinone \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.138 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -e CTRL_PERSIST_CONFIG=1 \
    -p 18300:18300 \
    -p 18301:18301 \
    -p 18400:18400 \
    -p 18401:18401 \
    -p 10443:10443 \
    -p 18301:18301/udp \
    -p 8443:8443 \
    -v /lib/modules:/lib/modules:ro \
    -v /var/neuvector:/var/neuvector \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
neuvector/allinone:5.3.3
```

3. 部署 scanner
```
$ docker run -td --name scanner \
-e CLUSTER_JOIN_ADDR=192.168.11.138 \
-e NV_PLATFORM_INFO=platform=Docker \
-p 18402:18402 -v /var/run/docker.sock:/var/run/docker.sock:ro \
neuvector/scanner:latest
```

4. 登入 NV

![image](https://hackmd.io/_uploads/HJxqb5GAC.png)


### 使用 docker-compose 安裝
```
$ cd /usr/bin

$ sudo wget https://github.com/docker/compose/releases/download/v2.29.7/docker-compose-linux-x86_64

$ sudo mv docker-compose-linux-x86_64 docker-compose

$ sudo chmod 755 docker-compose
```

* 編輯 docker-compose.yml
```
$ mkdir NV;cd NV

$ nano docker-compose.yml
version: '2'
services:
  allinone:
    pid: host
    image: neuvector/allinone:5.3.3
    container_name: allinone
    privileged: true
    environment:
        - CLUSTER_JOIN_ADDR=192.168.11.138
        - NV_PLATFORM_INFO=platform=Docker
        - CTRL_PERSIST_CONFIG=1
    ports:
        - 18300:18300
        - 18301:18301
        - 18400:18400
        - 18401:18401
        - 10443:10443
        - 18301:18301/udp
        - 8443:8443
    volumes:
        - /lib/modules:/lib/modules:ro
        - /var/neuvector:/var/neuvector
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - /proc:/host/proc:ro
        - /sys/fs/cgroup:/host/cgroup:ro
  scanner:
    image: neuvector/scanner:latest
    container_name: scanner
    environment:
      - CLUSTER_JOIN_ADDR=192.168.11.138
    ports:
      - 18402:18402
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
```
* 啟動 container
```
$ docker-compose up -d
```

* 登入 NV

![image](https://hackmd.io/_uploads/HJxqb5GAC.png)


## HA 部屬
* 部屬 3 個 Allinone node + 1 個 enforcer node
* 透過 `CLUSTER_JOIN_ADDR=192.168.11.137,192.168.11.138,192.168.11.139` 將三個 Allinone 的 NV 組成一個集群
* 需要宣告 `CTRL_PERSIST_CONFIG=1` 環境變數 NV 才會把備份設定存到 `/var/neuvector` 目錄
```
# 分別在三台 node 上執行
$ docker run -d --name allinone \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.137,192.168.11.138,192.168.11.139 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -e CTRL_PERSIST_CONFIG=1 \
    -p 18300:18300 \
    -p 18301:18301 \
    -p 18400:18400 \
    -p 18401:18401 \
    -p 10443:10443 \
    -p 18301:18301/udp \
    -p 8443:8443 \
    -v /lib/modules:/lib/modules:ro \
    -v /var/neuvector:/var/neuvector \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
neuvector/allinone:5.3.3
```
* 部屬 scanner
```
$ docker run -td --name scanner \
-e CLUSTER_JOIN_ADDR=192.168.11.137 \
-e NV_PLATFORM_INFO=platform=Docker \
-p 18402:18402 -v /var/run/docker.sock:/var/run/docker.sock:ro \
neuvector/scanner:latest
```

* 如果要再新增節點要透過 enforcer 的方式新增
```
# 在第四台 node 上執行
$ docker run -d --name enforcer \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.137,192.168.11.138,192.168.11.139 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -p 18301:18301 \
    -p 18401:18401 \
    -p 18301:18301/udp \
    -v /lib/modules:/lib/modules:ro \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
neuvector/enforcer:5.3.3
```

* 在 NV 介面可以看到有四個 node

![image](https://hackmd.io/_uploads/H1G-Gfd00.png)

* 可以看到第四個節點是 enforcer node

![image](https://hackmd.io/_uploads/rJKWfGORR.png)

## allinone manager UI 自簽憑證
* 產生自簽憑證
```
$ mkdir ssl; cd ssl

$ wget https://raw.githubusercontent.com/cooloo9871/SelfSigned-RootCA/refs/heads/master/mk

$ bash mk create nv.example.com 192.168.11.160
```

* 建立 allinone NV，須注意自己的憑證位置

```
$ docker run -d --name allinone \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.160 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -e CTRL_PERSIST_CONFIG=1 \
    -p 18300:18300 \
    -p 18301:18301 \
    -p 18400:18400 \
    -p 18401:18401 \
    -p 10443:10443 \
    -p 18301:18301/udp \
    -p 8443:8443 \
    -v /lib/modules:/lib/modules:ro \
    -v /var/neuvector:/var/neuvector \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
    -v /root/ssl/cert-key.pem:/etc/neuvector/certs/ssl-cert.key \
    -v /root/ssl/cert.pem:/etc/neuvector/certs/ssl-cert.pem \
neuvector/allinone:5.3.3
```
* 檢查憑證，輸出會與 cert.pem 內容一致
```
$ echo | \
    openssl s_client -servername nv.example.com -connect nv.example.com:8443 2>/dev/null | \
    openssl x509 -text
```


* 將 ca.pem 匯入瀏覽器後，可以 https 信任憑證，注意是 8443 port

![image](https://hackmd.io/_uploads/Bymcgpc0R.png)


## 使用 API 掃描本地 image
* 使用帳號密碼 login 產生 token
```
$ curl -s -k -X 'POST' \
  'https://192.168.11.138:10443/v1/auth' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "client_ip": "",
  "password": {
    "username": "admin",
    "password": "admin"
  },
  "Token": {
    "token": "",
    "state": "",
    "redirect_endpoint": ""
  }
}' | jq -r '.token.token' > token

# Keep login session alive
$ _token_=$(cat token)

$ curl -s -k -X 'PATCH' \
  'https://192.168.11.138:10443/v1/auth' \
  -H 'accept: application/json' \
  -H "X-Auth-Token: $_token_"
```

* 掃描本地 image

```
$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED       SIZE
neuvector/scanner    latest    a5813fe43c91   2 days ago    384MB
neuvector/allinone   5.4.0     6826eacb29f5   7 weeks ago   911MB

$ curl -s -k -H "Content-Type: application/json" -H "X-Auth-Token: $_token_" -d '{"request": {"tag": "latest", "repository": "neuvector/scanner", "scan_layers": true}}' "https://192.168.11.138:10443/v1/scan/repository" | jq .
{
  "report": {
    "author": "",
    "base_os": "sles:15.6",
    "checks": [
      {
        "automated": false,
        "category": "image",
        "description": "Ensure a user for the container has been created",
        "level": "WARN",
        "message": [],
        "profile": "Level 1",
        "remediation": "",
        "scored": true,
        "tags_v2": {},
        "test_number": "I.4.1",
        "type": "image"
      },
      {
        "automated": false,
        "category": "image",
        "description": "Ensure that HEALTHCHECK instructions have been added to container images",
        "level": "WARN",
        "message": [],
        "profile": "Level 1",
        "remediation": "",
        "scored": false,
        "tags_v2": {},
        "test_number": "I.4.6",
        "type": "image"
      },
......
```

## 升級

```
$ docker stop allinone

$ docker rename allinone allinone-bk
```
* 安裝新版本 NV
```
$ docker run -d --name allinone \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.105 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -e CTRL_PERSIST_CONFIG=1 \
    -p 18300:18300 \
    -p 18301:18301 \
    -p 18400:18400 \
    -p 18401:18401 \
    -p 10443:10443 \
    -p 18301:18301/udp \
    -p 8443:8443 \
    -v /lib/modules:/lib/modules:ro \
    -v /var/neuvector:/var/neuvector \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
neuvector/allinone:5.3.4
```

* NV 數據都是保存在 `/var/neuvector` 路徑下，只要有掛載這個路徑升級 NV 後原有的資料都還會存在。

## allinone Replacing Internal Certificates

### 部屬 allinone 節點
* 產生自簽名憑證
```
$ mkdir ssl; cd ssl

$ vim ca.cfg
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = TW
ST = Taipei
L = San Jose
O = NeuVector Inc.
OU = Neuvector
CN = Neuvector
[v3_req]
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = Neuvector


$ openssl genrsa -out ca.key 2048
$ openssl req -x509 -sha256 -new -nodes -key ca.key -days 3650 -subj "/C=TW/ST=Taipei/L=Taipei/O=NeuVector Inc./OU=Neuvector/CN=Neuvector" -out ca.crt
$ openssl genrsa -out tls.key 2048
$ openssl req -new -key tls.key -sha256 -out cert.csr -config ca.cfg

# 檢查 CSR 內容
$ openssl req -in cert.csr -noout -text
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = TW, ST = Taipei, L = San Jose, O = NeuVector Inc., OU = Neuvector, CN = Neuvector
......

# 簽署 CSR 成為 X.509 憑證
$ openssl x509 -req -sha256 -in cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt -days 3650 -extensions 'v3_req' -extfile ca.cfg

# 檢查 X.509 憑證的詳細內容
$ openssl x509 -in tls.crt -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            36:0a:3c:c5:84:cb:02:50:e7:7f:a8:ca:5b:a3:06:10:53:86:b3:3a
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = TW, ST = Taipei, L = Taipei, O = NeuVector Inc., OU = Neuvector, CN = Neuvector
......


$ NV:~/ssl # ls -l
total 32
-rw-r--r-- 1 root root  365 May 19 13:20 ca.cfg
-rw-r--r-- 1 root root 1363 May 19 13:22 ca.crt
-rw------- 1 root root 1704 May 19 13:21 ca.key
-rw-r--r-- 1 root root   41 May 19 13:25 ca.srl
-rw-r--r-- 1 root root 1017 May 19 13:23 cert.csr
-rw-r--r-- 1 root root 1436 May 19 13:25 tls.crt
-rw------- 1 root root 1704 May 19 13:23 tls.key

$ mv ca.crt ca.cert

$ mv tls.crt cert.pem

$ mv tls.key cert.key

$ NV:~/ssl # ls -l
total 32
-rw-r--r-- 1 root root 1363 May 19 13:22 ca.cert
-rw-r--r-- 1 root root  365 May 19 13:20 ca.cfg
-rw------- 1 root root 1704 May 19 13:21 ca.key
-rw-r--r-- 1 root root   41 May 19 13:25 ca.srl
-rw-r--r-- 1 root root 1017 May 19 13:23 cert.csr
-rw------- 1 root root 1704 May 19 13:23 cert.key
-rw-r--r-- 1 root root 1436 May 19 13:25 cert.pem

$ NV:~/ssl # pwd
/root/ssl
```
* 部屬 allinone，並指定掛載內部憑證
```
$ docker run -d --name allinone \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.119 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -e CTRL_PERSIST_CONFIG=1 \
    -p 18300:18300 \
    -p 18301:18301 \
    -p 18400:18400 \
    -p 18401:18401 \
    -p 10443:10443 \
    -p 18301:18301/udp \
    -p 8443:8443 \
    -v /lib/modules:/lib/modules:ro \
    -v /var/neuvector:/var/neuvector \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
    -v /root/ssl/:/etc/neuvector/certs/internal/:ro \
neuvector/allinone:5.3.3
```

### 部屬 enforcer 節點
* 將在 allinone 的憑證複製到 enforcer 節點上，並指定掛載內部憑證
```
$ scp -r ssl 192.168.11.118:~

$ docker run -d --name enforcer \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=192.168.11.119 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -p 18301:18301 \
    -p 18401:18401 \
    -p 18301:18301/udp \
    -v /lib/modules:/lib/modules:ro \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
    -v /root/ssl/:/etc/neuvector/certs/internal/:ro \
neuvector/enforcer:5.3.3
```

### 部屬 scanner 
* 指定掛載內部憑證
* 如果是部屬 5.4 以後的版本，scanner 的 tag 要換成 `6`，`neuvector/scanner:6`
```
$ docker run -td --name scanner \
-e CLUSTER_JOIN_ADDR=192.168.11.119 \
-e NV_PLATFORM_INFO=platform=Docker \
-p 18402:18402 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /root/ssl/:/etc/neuvector/certs/internal/:ro \
neuvector/scanner:latest
```

### 驗證
* 驗證所有 node 以及 System Components 都有正確連接。

![image](https://hackmd.io/_uploads/BJnULSdWxe.png)
![image](https://hackmd.io/_uploads/SkKDIH_Zex.png)
![image](https://hackmd.io/_uploads/Hy4O8H_Zxl.png)
![image](https://hackmd.io/_uploads/S1gt8SObgg.png)


## 注意 5.4.2 以後的版本都需要自己先產生內部憑證並掛載，因為後續版本的 NV 不會自己產生內部通訊用的憑證



## 在 Podman 安裝 allinone 5.4.4 

```
$ sudo podman version
Client:       Podman Engine
Version:      4.9.3
API Version:  4.9.3
Go Version:   go1.22.2
Built:        Thu Jan  1 08:00:00 1970
OS/Arch:      linux/amd64
```
使用 podman 做出 docker.sock
```
$ sudo mkdir /var/neuvector

$ sudo ln -s /run/podman/podman.sock /var/run/docker.sock

$ sudo ls -l /var/run/docker.sock
lrwxrwxrwx 1 root root 23 Jun 23 15:18 /var/run/docker.sock -> /run/podman/podman.sock
```
* 產生自簽名憑證
```
$ mkdir ssl; cd ssl

$ nano ca.cfg
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = TW
ST = Taipei
L = San Jose
O = NeuVector Inc.
OU = Neuvector
CN = Neuvector
[v3_req]
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = Neuvector


$ openssl genrsa -out ca.key 2048
$ openssl req -x509 -sha256 -new -nodes -key ca.key -days 3650 -subj "/C=TW/ST=Taipei/L=Taipei/O=NeuVector Inc./OU=Neuvector/CN=Neuvector" -out ca.crt
$ openssl genrsa -out tls.key 2048
$ openssl req -new -key tls.key -sha256 -out cert.csr -config ca.cfg

# 檢查 CSR 內容
$ openssl req -in cert.csr -noout -text
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = TW, ST = Taipei, L = San Jose, O = NeuVector Inc., OU = Neuvector, CN = Neuvector
......

# 簽署 CSR 成為 X.509 憑證
$ openssl x509 -req -sha256 -in cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt -days 3650 -extensions 'v3_req' -extfile ca.cfg

# 檢查 X.509 憑證的詳細內容
$ openssl x509 -in tls.crt -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            36:0a:3c:c5:84:cb:02:50:e7:7f:a8:ca:5b:a3:06:10:53:86:b3:3a
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = TW, ST = Taipei, L = Taipei, O = NeuVector Inc., OU = Neuvector, CN = Neuvector
......


$ NV:~/ssl # ls -l
total 32
-rw-r--r-- 1 root root  365 May 19 13:20 ca.cfg
-rw-r--r-- 1 root root 1363 May 19 13:22 ca.crt
-rw------- 1 root root 1704 May 19 13:21 ca.key
-rw-r--r-- 1 root root   41 May 19 13:25 ca.srl
-rw-r--r-- 1 root root 1017 May 19 13:23 cert.csr
-rw-r--r-- 1 root root 1436 May 19 13:25 tls.crt
-rw------- 1 root root 1704 May 19 13:23 tls.key

$ mv ca.crt ca.cert

$ mv tls.crt cert.pem

$ mv tls.key cert.key

$ NV:~/ssl # ls -l
total 32
-rw-r--r-- 1 root root 1363 May 19 13:22 ca.cert
-rw-r--r-- 1 root root  365 May 19 13:20 ca.cfg
-rw------- 1 root root 1704 May 19 13:21 ca.key
-rw-r--r-- 1 root root   41 May 19 13:25 ca.srl
-rw-r--r-- 1 root root 1017 May 19 13:23 cert.csr
-rw------- 1 root root 1704 May 19 13:23 cert.key
-rw-r--r-- 1 root root 1436 May 19 13:25 cert.pem

$ NV:~/ssl # pwd
/root/ssl
```
* 部屬 allinone，並指定掛載內部憑證
```
$ sudo podman run -d --name allinone \
--pid=host \
--privileged \
    -e CLUSTER_JOIN_ADDR=10.10.7.43 \
    -e NV_PLATFORM_INFO=platform=Docker \
    -e CTRL_PERSIST_CONFIG=1 \
    -p 18300:18300 \
    -p 18301:18301 \
    -p 18400:18400 \
    -p 18401:18401 \
    -p 10443:10443 \
    -p 18301:18301/udp \
    -p 8443:8443 \
    -v /lib/modules:/lib/modules:ro \
    -v /var/neuvector:/var/neuvector \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /sys/fs/cgroup:/host/cgroup:ro \
    -v /proc:/host/proc:ro \
    -v /home/bigred/ssl:/etc/neuvector/certs/internal/:ro \
docker.io/neuvector/allinone:5.4.4
```

* 佈署 scanner
```
$ sudo podman run -td --name scanner \
-e CLUSTER_JOIN_ADDR=10.10.7.43 \
-e NV_PLATFORM_INFO=platform=Docker \
-p 18402:18402 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /home/bigred/ssl:/etc/neuvector/certs/internal/:ro \
docker.io/neuvector/scanner:6
```
```
$ sudo podman ps -a
CONTAINER ID  IMAGE                               COMMAND     CREATED         STATUS         PORTS                                                                                                                                                   NAMES
05086fd23737  docker.io/neuvector/allinone:5.4.4              58 seconds ago  Up 59 seconds  0.0.0.0:18301->18301/udp, 0.0.0.0:8443->8443/tcp, 0.0.0.0:10443->10443/tcp, 0.0.0.0:18300-18301->18300-18301/tcp, 0.0.0.0:18400-18401->18400-18401/tcp  allinone
cf2e1b87978a  docker.io/neuvector/scanner:6                   3 seconds ago   Up 4 seconds   0.0.0.0:18402->18402/tcp                                                                                                                                scanner
```


