Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NODE_ENV=development

# EdgeOps Console static embed (npm run build:console → dev/console/build)
EDGEOPS_CONSOLE_PATH=dev/console/build # must be absolute path
EDGEOPS_CONSOLE_VERSION=v1.0.9
EDGEOPS_CONSOLE_VERSION=v1.0.10
# EDGEOPS_CONSOLE_REPO=https://github.com/Datasance/edgeops-console
# EDGEOPS_CONSOLE_FLAVOR=datasance

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/set-build-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ runs:
shell: bash
run: |
VERSION="${{ env.EDGEOPS_CONSOLE_VERSION }}"
if [ -z "$VERSION" ]; then VERSION="1.0.9"; fi
if [ -z "$VERSION" ]; then VERSION="1.0.10"; fi
echo "EDGEOPS_CONSOLE_VERSION=$VERSION" >> "${GITHUB_ENV}"

REPO="${{ env.EDGEOPS_CONSOLE_REPO }}"
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
# Changelog


## [v3.8.1] - 2026-07-11

Patch release: EdgeOps Console refresh, console caching, RBAC and upload hardening, cluster-controller list filtering, and application-template deploy cleanup.

### Added

- **`GET /api/v3/cluster/controllers`** — optional query param **`includeInactive=true`** returns historical inactive replica rows; default list excludes inactive controllers.
- **`scripts/check-dockerfile-digests.sh`** — skopeo-based check that digest-pinned Dockerfile base images match current registry manifest lists (multi-arch aware).

### Changed

- Embedded **EdgeOps Console** default version **v1.0.9** → **v1.0.10** (Dockerfile, Makefile, CI build env, `.env.example`, `build-console-dev.js`).
- **`multer`** upgraded to **2.2.0**; multipart uploads capped at **1** file, **10** fields, **`fieldNestingDepth: 0`**.
- Dockerfile base image digest pins refreshed for **`node:24-bookworm`** and **`ubi9/nodejs-24-minimal`**.
- EdgeOps Console static serving — **`Cache-Control`** policy: **`no-cache`** for `index.html` and SPA fallbacks, **`no-store`** for `controller-config.js`, **`immutable`** long cache for hashed **`assets/`**, **24h** cache for **`branding/`**.

### Fixed

- **RBAC authorization pool pressure** — fresh RBAC cache hits serve cached allow/deny decisions without opening a DB transaction; full auth path runs only on cache miss or stale version.
- **Multipart upload DoS** — multer limits mitigate unbounded field nesting / file count abuse on file-upload routes.
- **Application template deploy** — template populate excludes **`created_at`** / **`updated_at`** so deploy-from-template does not leak template metadata into the generated application payload.

---

## [v3.8.0] - 2026-07-03

Controller v3.8 is a **greenfield** release aligned with **Edgelet**. There is **no upgrade path** from v3.7: use a fresh database and redeploy Controller + Edgelet together.
Expand Down
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# ioFog overrides: EDGEOPS_CONSOLE_REPO=https://github.com/eclipse-iofog/edgeops-console
# EDGEOPS_CONSOLE_FLAVOR=iofog
# node:24-bookworm — pin manifest list digest for reproducible multi-arch builds
FROM node:24-bookworm@sha256:fdddfb3e688158251943d52eba361de991548f6814007acba4917ae6b512d6be AS console-builder
FROM node:24-bookworm@sha256:392e1e23f34da768d8d1f4e502b64f200d3be3465934d4b7930f57d7e2fc1989 AS console-builder

ARG EDGEOPS_CONSOLE_REPO=https://github.com/Datasance/edgeops-console
ARG EDGEOPS_CONSOLE_VERSION=v1.0.9
ARG EDGEOPS_CONSOLE_VERSION=v1.0.10
ARG EDGEOPS_CONSOLE_FLAVOR=datasance

RUN apt-get update \
Expand All @@ -28,7 +28,7 @@ RUN test -f build/index.html \
&& cp -a build /tmp/console/build


FROM node:24-bookworm@sha256:fdddfb3e688158251943d52eba361de991548f6814007acba4917ae6b512d6be AS builder
FROM node:24-bookworm@sha256:392e1e23f34da768d8d1f4e502b64f200d3be3465934d4b7930f57d7e2fc1989 AS builder

ARG PKG_VERSION

Expand All @@ -48,9 +48,9 @@ RUN npm pack


# ubi9/nodejs-24-minimal:latest — pin manifest list digest for reproducible multi-arch builds
FROM registry.access.redhat.com/ubi9/nodejs-24-minimal@sha256:5f1ac8eab93c93eb2227f4ee7822668b312ee292d122dddd580bee8f17359c2f
FROM registry.access.redhat.com/ubi9/nodejs-24-minimal@sha256:c71bc3282e204a2b09143d2621236ebc83ef149af67ba2604ba43ad3ec21a5fb

ARG EDGEOPS_CONSOLE_VERSION=v1.0.9
ARG EDGEOPS_CONSOLE_VERSION=v1.0.10
ARG IMAGE_REGISTRY
ARG OCI_SOURCE_REPO
ARG CONTROLLER_DISTRIBUTION=iofog
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Local Docker build — mirrors CI/release build-args (see .github/actions/set-build-env).
# Override any variable: make build FLAVOR=iofog EDGEOPS_CONSOLE_VERSION=v1.0.9
# Override any variable: make build FLAVOR=iofog EDGEOPS_CONSOLE_VERSION=v1.0.10

FLAVOR ?= datasance
IMAGE_NAME ?= controller
Expand All @@ -25,7 +25,7 @@ else
$(error FLAVOR must be "datasance" or "iofog", got "$(FLAVOR)")
endif

EDGEOPS_CONSOLE_VERSION ?= v1.0.9
EDGEOPS_CONSOLE_VERSION ?= v1.0.10

IMAGE_REF = $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(DOCKER_TAG)

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "controller",
"version": "3.8.0",
"version": "3.8.1",
"description": "A cloud-native operations controller for managing edge computing workloads, edgelet nodes, and deployments across Eclipse IoFog and Datasance PoT.",
"main": "./src/main.js",
"author": "Eclipse ioFog Project",
Expand Down
2 changes: 1 addition & 1 deletion scripts/build-console-dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const CONSOLE_DIR = path.join(DEV_DIR, 'console')
const BUILD_OUT = path.join(CONSOLE_DIR, 'build')

const REPO = process.env.EDGEOPS_CONSOLE_REPO || 'https://github.com/Datasance/edgeops-console'
const VERSION = process.env.EDGEOPS_CONSOLE_VERSION || 'v1.0.9'
const VERSION = process.env.EDGEOPS_CONSOLE_VERSION || 'v1.0.10'
const FLAVOR = process.env.EDGEOPS_CONSOLE_FLAVOR || 'datasance'

function normalizeTag (version) {
Expand Down
24 changes: 23 additions & 1 deletion src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,33 @@ initialize().then(() => {
const hasFileBasedTLS = tlsMaterial.enabled && !tlsMaterial.isBase64
const hasBase64TLS = tlsMaterial.enabled && tlsMaterial.isBase64

consoleApp.use(express.static(consolePath, { index: 'index.html' }))
function setConsoleStaticCacheHeaders (res, filePath) {
if (filePath.endsWith('index.html')) {
res.setHeader('Cache-Control', 'no-cache')
return
}
if (filePath.endsWith('controller-config.js')) {
res.setHeader('Cache-Control', 'no-store')
return
}
if (filePath.includes(`${path.sep}assets${path.sep}`)) {
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
return
}
if (filePath.includes(`${path.sep}branding${path.sep}`)) {
res.setHeader('Cache-Control', 'public, max-age=86400')
}
}

consoleApp.use(express.static(consolePath, {
index: 'index.html',
setHeaders: setConsoleStaticCacheHeaders
}))
consoleApp.get('*', (req, res, next) => {
if (path.extname(req.path)) {
return next()
}
res.setHeader('Cache-Control', 'no-cache')
res.sendFile(path.join(consolePath, 'index.html'), (error) => {
if (error) {
next(error)
Expand Down
3 changes: 2 additions & 1 deletion src/services/application-template-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ const getApplicationTemplateEndPoint = async function (name, isCLI, transaction)
const getApplicationDataFromTemplate = async function (deploymentData, isCLI, transaction) {
await Validator.validate(deploymentData, Validator.schemas.applicationTemplateDeploy)

const applicationTemplateDBObject = await ApplicationTemplateManager.findOnePopulated({ name: deploymentData.name }, transaction)
const attributes = { exclude: ['created_at', 'updated_at'] }
const applicationTemplateDBObject = await ApplicationTemplateManager.findOnePopulated({ name: deploymentData.name }, attributes, transaction)
if (!applicationTemplateDBObject) {
throw new Errors.NotFoundError(ErrorMessages.INVALID_APPLICATION_TEMPLATE_NAME, deploymentData.name)
}
Expand Down
Loading