Skip to content

Commit 8806c72

Browse files
author
Vadim Bogulean
committed
Separate DB and App/CLI to separate containers.
1 parent c3cb6d4 commit 8806c72

File tree

9 files changed

+233
-175
lines changed

9 files changed

+233
-175
lines changed

.env

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
POSTGRES_PASSWORD="postgres_password"
21
FCDB_USER="fastcve_db_user"
32
FCDB_PASS="fastcve_db_pass"
3+
INP_ENV_NAME="dev"
44
FASTCVE_DOCKER_IMG="binare/fastcve"
5+
FASTCVE_DB_IMAGE="postgres:16-alpine3.19"
56
FASTCVE_DOCKER_TAG="latest"
6-
NVD_API_KEY=
7+
NVD_API_KEY=

Dockerfile

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
1-
FROM postgres:16-alpine3.19
1+
FROM python:3.12-slim
22

33
ARG APP_VERSION=notset
44

5-
ENV FCDB_HOME=/fastcve FCDB_NAME=vuln_db POSTGRES_PASSWORD= FCDB_USER= FCDB_PASS= INP_ENV_NAME=dev
6-
ENV PATH=${FCDB_HOME}:$PATH
7-
8-
RUN apk add gcc g++ build-base python3-dev py3-pip
5+
ENV FCDB_HOME=/fastcve \
6+
INP_ENV_NAME=${INP_ENV_NAME} \
7+
PYTHONPATH=/fastcve \
8+
PATH=/fastcve:$PATH \
9+
APP_VERSION=${APP_VERSION}
910

1011
WORKDIR ${FCDB_HOME}
1112

12-
COPY ./src/config/requirements.txt /tmp
13-
14-
RUN pip install --break-system-packages -r /tmp/requirements.txt
13+
COPY ./src/config/requirements.txt /tmp/requirements.txt
14+
RUN pip install --no-cache-dir -r /tmp/requirements.txt
1515

16-
COPY ./docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
17-
COPY ./start_web.sh /always-init.d/start_web.sh
1816
COPY ./src ${FCDB_HOME}
1917

20-
RUN sed -i "1i\export APP_VERSION=${APP_VERSION}" ${FCDB_HOME}/config/setenv/setenv_*
21-
22-
RUN mkdir -p ${FCDB_HOME}/logs && chmod +wx ${FCDB_HOME}/logs \
23-
&& chmod +x ${FCDB_HOME}/db/setup_db.sh \
24-
&& chmod +x ${FCDB_HOME}/db/schema.sh \
25-
&& chmod -x ${FCDB_HOME}/config/setenv.sh \
26-
&& ln -s ${FCDB_HOME}/db/setup_db.sh /docker-entrypoint-initdb.d \
27-
&& ln -s ${FCDB_HOME}/config/setenv.sh /docker-entrypoint-initdb.d \
28-
&& chown -R postgres:postgres ${FCDB_HOME}
18+
EXPOSE 8000
2919

30-
USER postgres
20+
CMD ["uvicorn", "web.app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

README.md

Lines changed: 121 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,103 +12,178 @@ Overall, `fastcve` is a useful tool for anyone who is interested in keeping up-t
1212
Technical details
1313
-----------------
1414

15+
Some key technical characteristics of `fastcve`:
1516

16-
Some key technical characteristics of `fastcve` tool:
17+
1. **Docker containerization**: Runs as a Docker Compose stack with two services: `fastcve` (API + CLI) and `fastcve-db` (PostgreSQL).
1718

18-
1. **Docker containerization**: This tool would run as a Docker container, meaning it is packaged and runs as a standalone executable unit that includes all its dependencies. This makes it easy to deploy and run the tool on any system that supports Docker.
19+
2. **Automatically creates the DB on first start**: PostgreSQL creates the initial database (`POSTGRES_DB`) when the DB volume is empty.
1920

20-
2. **Automatically creates the DB on first start**: The tool would automatically create the database when it is started for the first time, eliminating the need for manual setup.
21+
3. **Automatically creates and upgrades the DB schema if needed**: The schema is created/updated automatically on app start and before CLI commands run.
2122

22-
3. **Automatically creates and upgrades the DB schema if needed**: The tool would automatically manage the database schema, creating it when necessary and upgrading it as needed to support new features or changes in the data structure.
23+
4. **Capability to populate the DB using external sources**: The `load` command can populate the DB from NVD (CVE/CPE via NVD 2.0 APIs) and additional sources (MITRE CWE/CAPEC, EPSS, CISA KEV).
2324

24-
3. **Capability to populate the DB using NVD APIs (2.0)**: The tool would have the capability to populate the database using APIs from the National Vulnerability Database (NVD), a comprehensive database of vulnerabilities that is maintained by the US National Institute of Standards and Technology.
25+
5. **Incremental updates**: Re-running `load` fetches only changes since the last successful update (NVD increments are limited to `fetch.max.days.period`, default 120 days).
2526

26-
4. **Automatically updates the DB schema for the latest changes from the previous update**: The tool would automatically update the database with the latest changes, new vulnerabilities, and new Common Platform Enumeration (CPE) entries, ensuring that the database remains up-to-date and relevant.
27+
The tool is a comprehensive solution for managing a local vulnerability database and querying it via CLI and HTTP API.
2728

28-
The tool is a comprehensive solution for managing a database of vulnerabilities, Common Platform Enumeration (CPE) entries, designed to make it easy to keep the database up-to-date and relevant, and to simplify the process of querying the database for vulnerabilities and information about them.
29-
30-
It was designed to be able to handle multiple query entries and maintain a high level of performance. It is optimized to be able to handle a large number of queries efficiently and quickly. The goal is to provide a fast and reliable solution for searching, maintaining and updating information about vulnerabilities and their corresponding CPE entries. The tool is also able to provide information about CWE (Common Weakness Enumerations) and CAPEC (Common Attack Pattern Enumerations and Classification)
29+
It is optimized to handle many queries efficiently, and to keep vulnerability data up to date via incremental updates.
3130

3231

3332
Build
3433
----------
3534

3635

37-
In order to build the docker image you need to trigger:
38-
```
39-
docker compose build
36+
To build the application image:
37+
```bash
38+
docker compose build fastcve
4039
```
4140

42-
this would create a new image named as `fastcve:latest`. In case a special tag is needed then export before hand ENV var `DOCKER_TAG=<your_tag>` to generate `fastcve:<your_tag>`
41+
This builds `${FASTCVE_DOCKER_IMG}:${FASTCVE_DOCKER_TAG}` (application / API / CLI). The default values are in `.env`.
42+
43+
The DB container uses an upstream PostgreSQL image (defaults to `postgres:16-alpine3.19`, configurable via `FASTCVE_DB_IMAGE`) and is not built from this repo.
44+
45+
If you need a custom tag, set `FASTCVE_DOCKER_TAG=<your_tag>` to generate `${FASTCVE_DOCKER_IMG}:<your_tag>`.
46+
47+
48+
Migration (single-container -> split DB/app)
49+
--------------------------------------------
50+
51+
Previous versions (-> v1.2.3) ran the PostgreSQL DB and the FastCVE API/CLI in the same `fastcve` container. The current `docker-compose.yml` splits this into two services: `fastcve-db` (PostgreSQL) and `fastcve` (API/CLI).
52+
53+
To migrate an existing deployment:
54+
55+
1. Stop the old container/stack **without deleting the DB volume**:
56+
```
57+
docker compose down
58+
```
59+
60+
2. Update your environment variables / `.env` for the new compose file:
61+
- Keep `FCDB_USER` and `FCDB_PASS` the same as before (so the existing DB user credentials still match).
62+
- `FCDB_USER`/`FCDB_PASS` are used for both:
63+
- the app connection (`postgresql://${FCDB_USER}:${FCDB_PASS}@...`), and
64+
- PostgreSQL initialization (`POSTGRES_USER`/`POSTGRES_PASSWORD`) when the DB volume is empty.
65+
- For Docker Compose deployments, set `INP_ENV_NAME=dev` (the default). (`setenv_dev.ini` points to the in-stack DB hostname `fastcve-db`.)
66+
- (Optional) Set `FASTCVE_DB_IMAGE` if you need a different PostgreSQL image/tag.
67+
68+
3. If you previously bind-mounted `/fastcve/config/setenv` from the host, ensure the *mounted* `setenv_${INP_ENV_NAME}.ini` matches the new split:
69+
- `FCDB_HOST=fastcve-db`
70+
- `FCDB_PORT=5432`
71+
72+
4. Start the new split stack:
73+
```
74+
docker compose up -d
75+
```
76+
77+
Notes:
78+
- The DB data is still kept in the Docker volume `vol_fastcve_db`. Do not use `docker compose down -v` unless you intentionally want to wipe the DB.
79+
- If your existing `vol_fastcve_db` was created by an older PostgreSQL *major* version, you must do a `pg_dump`/restore (PostgreSQL data directories are not forward-compatible across major versions).
80+
- DB admin commands that used to run in `fastcve` now run in `fastcve-db` (example: `docker compose exec fastcve-db psql -U "$POSTGRES_USER" -d "$POSTGRES_DB"`).
81+
- If you change `FCDB_PASS` for an already-initialized `vol_fastcve_db`, PostgreSQL will *not* automatically update the user password; you must run `ALTER USER ... PASSWORD ...` (or recreate the volume).
4382

4483

4584
First Run
4685
---------
4786

48-
Before starting the container for the first time several env variables has to be exported first:
49-
```
50-
export INP_ENV_NAME=<the env name from where settings to be read . i.e.:dev>
51-
export POSTGRES_PASSWORD=<password for postgre DB user>
52-
export FCDB_USER=<fastcve DB User Name>
53-
export FCDB_PASS=<fastcve DB User Password>
87+
Docker Compose reads `.env` automatically. The defaults in this repo are enough to start a local stack.
88+
89+
Create a local folder for the `/backup` bind-mount used by `fastcve-db` (Linux):
90+
```bash
91+
mkdir -p backup && chmod 1777 backup
5492
```
5593

56-
To run the container:
94+
If you want to override them, set variables in your shell or edit `.env`:
95+
```bash
96+
export INP_ENV_NAME=dev
97+
export FCDB_USER=fastcve_db_user
98+
export FCDB_PASS=fastcve_db_pass
99+
export FASTCVE_DOCKER_IMG=binare/fastcve
100+
export FASTCVE_DOCKER_TAG=latest
57101
```
58-
docker compose up
102+
103+
To start the stack:
104+
```bash
105+
docker compose up -d --build
59106
```
60107

108+
Troubleshooting
109+
---------------
110+
111+
- `password authentication failed for user ...`: the DB is stored in `vol_fastcve_db`, so if the volume was initialized with different credentials you must reset it with `docker compose down -v` (or manually `ALTER USER` inside Postgres).
112+
61113
Configuration parameters
62114
------------------------
63115

64-
The docker container holds the relevant configuration files under `/fastcve/config/setenv`
65-
This map would contain the following files:
66-
- `config.ini` - contains app related config parameters
67-
- `setenv_<${INP_ENV_NAME}>.ini` - contains parameters that are env dependent as per the `INP_ENV_NAME` env variable value.
116+
The application container contains the configuration under `/fastcve/config`:
117+
- `/fastcve/config/setenv/config.ini` - main config (DB DSN, fetch URLs, sync settings, etc.)
118+
- `/fastcve/config/setenv/setenv_${INP_ENV_NAME}.ini` - env-specific settings loaded by `/fastcve/config/setenv.sh`
68119

69-
For an easy access and modification of the config files, mapping between HOST and container's folder `/fastcve/config/setenv` is recomended that can be specified in the `docker-compose.yml` file.
120+
In this repo, those files are located under `src/config` and are copied into the image during build.
121+
122+
For easier local edits, you can bind-mount config into the `fastcve` container (example):
123+
```yaml
124+
volumes:
125+
- ./src/config/setenv:/fastcve/config/setenv
126+
- ./src/config/setenv.sh:/fastcve/config/setenv.sh
127+
```
128+
129+
Note: `INP_ENV_NAME=prod` is not configured for Docker Compose out-of-the-box (`setenv_prod.ini` uses `FCDB_HOST=localhost`). For the split stack, use `dev` or update `setenv_prod.ini` to point to `fastcve-db:5432`.
70130

71131
How To
72132
------
73133

74134

75-
- **Populate the CVE, CPE, CWE, and CAPEC data for the first time**:
135+
- **Backup the DB (pg_dump, compact)**:
136+
> Important:
137+
> The dump is written inside the DB container to `/backup` (bind-mounted from the host via `docker-compose.yml`).
138+
> Ensure the host `./backup` directory exists and is writable (Linux):
139+
> `mkdir -p backup && chmod 1777 backup`
140+
141+
```bash
142+
docker compose exec -T fastcve-db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc -Z 9 -f "/backup/fastcve_vuln_db_$(date +%F).dump"'
76143
```
77-
docker exec fastcve load --data cve cpe cwe capec
144+
145+
Restore:
146+
```bash
147+
docker compose exec -T fastcve-db sh -c 'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists "/backup/fastcve_vuln_db_YYYY-MM-DD.dump"'
78148
```
79149

80-
- **Populate the CVE, and CPE data for the next times**:
150+
- **Populate the DB for the first time (CVE/CPE/CWE/CAPEC/EPSS/KEV)**:
151+
```bash
152+
docker compose exec fastcve load --data cve cpe cwe capec epss kev
81153
```
82-
docker exec fastcve load --data cve cpe
154+
155+
- **Update CVE/CPE incrementally (and refresh EPSS/KEV)**:
156+
```bash
157+
docker compose exec fastcve load --data cve cpe epss kev
83158
```
84159

85-
this will fetch the new/modified data for the period from the last data fetch (for a max of `n` days: parameter set in the config. NVD is allowing max 120 days period)
160+
This fetches changes since the last successful update (for CVE/CPE), with an upper limit of `fetch.max.days.period` (default 120 days) enforced by the loader.
86161

87-
If there is a need to repopulate the DB for the CWE/CAPEC info, then `--full` and `--drop` options are available for the CWE/CAPEC info load command. `--full` will cause to ignore the fact the CWE/CAPEC data is already present and `--drop` will cause to drop any exiting CWE/CAPEC related data before processing the new downloaded data. When using `--data epss` in combination with `--epss-now`, the load command explicitly fetches the EPSS data for the current date. If `--epss-now` is not specified, the script defaults to retrieve EPSS data from the previous day.
162+
If there is a need to repopulate the DB for the CWE/CAPEC info, then `--full` and `--drop` options are available for the load command. `--full` ignores the fact the data is already present and `--drop` drops existing data before loading. When using `--data epss` in combination with `--epss-now`, the loader fetches EPSS data for the current date; otherwise it defaults to the previous day.
88163

89164
- search for the data: **get the CVEs details (JSON) for a list of CVE-IDs**
90165
```
91-
docker exec fastcve search --search-info cve --cve CVE-YEAR-ID1 CVE-YEAR-ID2
166+
docker compose exec fastcve search --search-info cve --cve CVE-YEAR-ID1 CVE-YEAR-ID2
92167
```
93168

94169
- search for the data: **search CVEs by the summary text**
95170
```
96-
docker exec fastcve search --search-info cve --keyword '(buffer overflow|memory corruption).*before.*2\.1[0-9]'
171+
docker compose exec fastcve search --search-info cve --keyword '(buffer overflow|memory corruption).*before.*2\.1[0-9]'
97172
```
98-
Above will search in the CVE text and return the details of those CVEs that would match the summary/description text with the specified keyword. It is possible to specify more than one keywords and each keyword can be specified in form of regexp pattern. If multiple keywords are specified, it would consider as AND condition between the keywords.
173+
Above will search CVE text and return details for CVEs that match the given keyword(s). Multiple `--keyword` values are treated as an AND condition. Each keyword can be a regular expression.
99174

100175
- search for the data: **get the CVEs IDs for a specific CPE**
101176
```
102-
docker exec fastcve search --search-info cve --cpe23 cpe:2.3:*:*:linux_kernel:2.6.32: --output id
177+
docker compose exec fastcve search --search-info cve --cpe23 cpe:2.3:*:*:linux_kernel:2.6.32: --output id
103178
```
104179

105-
above will return the list of CVE-IDs that are related to `linux_kernel` product for version 2.6.32.
180+
Above will return the list of CVE-IDs that are related to the `linux_kernel` product for version 2.6.32.
106181

107-
To get the CVE details, request the output in JSON format: `--output json`.
182+
To get the CVE details, request the output in JSON format: `--output json`.
108183

109184
To get only those CVEs that were modified in the last `n` days, add the option `--days-back n` i.e. `--days-back 10` - only created/modified in the last **10** days
110185

111-
additional filters are available for the search in CVE DB:
186+
Additional filters are available for CVE search:
112187
```
113188
--cvss-severity-v2 {low, medium, high} # retrieve only those CVEs that has the severity as per CVSS score Version 2
114189
--cvss-severity-v3 {low, medium, high, critical} # retrieve only those CVEs that has the severity as per CVSS score Version 3.x
@@ -123,34 +198,35 @@ additional filters are available for the search in CVE DB:
123198
- search for the data: **get the valid list of CPE names for a query on part/vendor/product/version etc**.
124199

125200
```
126-
docker exec fastcve search --search-info cpe --cpe23 cpe:2.3:h:*:dl*:*: --output id
201+
docker compose exec fastcve search --search-info cpe --cpe23 cpe:2.3:h:*:dl*:*: --output id
127202
```
128203

129204
Above will search for all valid existing CPE 2.3 names that are of hardware type, for any vendor, product starts with `dl`*, and version is any
130205

131206
To see for the other options available for both `load` and `search` commands run these with `-h` option
132207

133208
```
134-
docker exec fastcve search -h
135-
docker exec fastcve load -h
209+
docker compose exec fastcve search -h
210+
docker compose exec fastcve load -h
136211
```
137212
138-
The same search capabilities are exposed through the web interface as well. The web interface is exposed through port 8000 by default. Can be changed in the `docker-compose.yml` file.
213+
The same search capabilities are exposed through the API (FastAPI). The API is exposed through port 8000 by default and can be changed in `docker-compose.yml`.
139214
140215
The following endpoints are exposed through HTTP requests
141216
```
217+
/status - DB status
142218
/api/search/cve - search for CVE data
143219
/api/search/cpe - search for CPE data
144220
/api/search/cwe - search for CWE data
145221
/api/search/capec - search for CAPEC data
146222
```
147223
148-
For the api definitions and execution instructions you can access on
224+
OpenAPI docs:
149225
```
150226
http://localhost:8000/docs
151227
```
152228
153-
For the API documentation you can access on
229+
Alternative docs view:
154230
```
155231
http://localhost:8000/redoc
156232
```

docker-compose.yml

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,64 @@
11
services:
22
#--------------------------------------------------------------------------
3-
# Application Database service
3+
# Database service
4+
#--------------------------------------------------------------------------
5+
fastcve-db:
6+
image: "${FASTCVE_DB_IMAGE:-postgres:16-alpine3.19}"
7+
8+
container_name: fastcve-db
9+
10+
environment:
11+
- POSTGRES_USER=${FCDB_USER}
12+
- POSTGRES_PASSWORD=${FCDB_PASS}
13+
- POSTGRES_DB=vuln_db
14+
15+
volumes:
16+
- vol_fastcve_db:/var/lib/postgresql/data
17+
- ./backup:/backup
18+
19+
ports:
20+
- "6630:5432"
21+
22+
healthcheck:
23+
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
24+
interval: 5s
25+
timeout: 3s
26+
retries: 10
27+
28+
networks:
29+
backend:
30+
aliases:
31+
- fastcve-db
32+
33+
#--------------------------------------------------------------------------
34+
# FastCVE application (API + CLI)
435
#--------------------------------------------------------------------------
536
fastcve:
637
image: "${FASTCVE_DOCKER_IMG}:${FASTCVE_DOCKER_TAG}"
738

839
container_name: fastcve
940

10-
command: postgres ${ENV_POSTGRES_CONF}
11-
1241
build:
1342
context: $PWD
1443
dockerfile: $PWD/Dockerfile
1544

1645
args:
1746
APP_VERSION: ${FASTCVE_DOCKER_TAG:-notset}
1847

48+
depends_on:
49+
fastcve-db:
50+
condition: service_healthy
51+
1952
environment:
20-
- INP_ENV_NAME=${INP_ENV_NAME}
21-
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
53+
- INP_ENV_NAME=${INP_ENV_NAME:-dev}
2254
- FCDB_USER=${FCDB_USER}
2355
- FCDB_PASS=${FCDB_PASS}
2456
- FCDB_WEB_PARAMS=--host 0.0.0.0 --port 8000 --workers 4
2557
- NVD_API_KEY=${NVD_API_KEY}
2658

27-
volumes:
28-
- vol_fastcve_db:/var/lib/postgresql/data
29-
#- ./src/config/setenv/:/fastcve/config/setenv/
30-
- ./:/tmp
59+
command: ["/bin/sh", "-c", "python -m web.prestart && exec uvicorn web.app:app $$FCDB_WEB_PARAMS"]
3160

3261
ports:
33-
- "6630:5432"
3462
- "8000:8000"
3563

3664
networks:

0 commit comments

Comments
 (0)