Skip to content

Conversation

@vhPedroGitHub
Copy link

@vhPedroGitHub vhPedroGitHub commented Dec 28, 2025

Hi. My team are working on these features. I hope this is helpful

look here: https://github.com/networkgcorefullcode
see info about the ssm here: https://github.com/networkgcorefullcode/ssm
We have updated udm, sd-core-helm-charts and OnRamp, and we have run simulations to test the new functionality

  • API for managing K4 (encryption keys)
  • Modules for handling the client and login in both options
  • Login to Vault with AppRole, Kubernetes, and certificates
  • Optimization of the subscriber synchronization process when a network slice or device group was updated, and also when a subscriber was deleted
  • Sync and health check modules for Vault and SSM
  • Web UI with vanilla JS
  • Implementation of pagination and filtering for the get users endpoint
  • Improvements to device group and network slice validations
  • Tests for the integrated functionalities
  • New models

Signed-off-by: Pedro Valdes pedrovh040110@gmail.com

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive Vault/SSM integration functionality to Aether Core, including a full-featured vanilla JavaScript web UI for managing 5G network components. The changes enable secure key management (K4 encryption keys), subscriber management with pagination and filtering, and improved device group and network slice validations.

Key changes:

  • Complete web UI implementation with vanilla JavaScript modules for managing device groups, network slices, gNB/UPF inventory, K4 keys, and subscribers
  • K4 key management API with encryption support (AES, DES, DES3)
  • Pagination and filtering for subscriber list endpoint
  • Enhanced subscriber synchronization processes
  • Admin operations for SSM sync, health checks, and K4 key rotation

Reviewed changes

Copilot reviewed 143 out of 147 changed files in this pull request and generated 24 comments.

Show a summary per file
File Description
ui/frontend_files/index.html Complete web console UI with navigation, sections for all entities, modals, and notifications
ui/frontend_files/styles.css Comprehensive styling with animations, responsive design, and custom components
ui/frontend_files/app.js Main application entry point with global state management and event handlers
ui/frontend_files/modules/baseManager.js Base class providing common CRUD operations for all entity managers
ui/frontend_files/modules/deviceGroups.js Device group management with IMSI configuration and QoS settings
ui/frontend_files/modules/networkSlices.js Network slice management with gNodeB, UPF, and application filtering rules
ui/frontend_files/modules/gnbInventory.js gNB (5G base station) inventory management
ui/frontend_files/modules/upfInventory.js UPF (User Plane Function) inventory management
ui/frontend_files/modules/k4.js K4 encryption key management with support for multiple key types
ui/frontend_files/modules/subscribers.js Subscriber management with pagination, filtering, and detailed authentication views
ui/frontend_files/modules/uiManager.js UI navigation and section management
ui/frontend_files/modules/modalManager.js Modal dialog management for create/edit operations
ui/frontend_files/modules/notifications.js Toast notification system for user feedback
ui/frontend_files/modules/objectsModels/*.js JavaScript equivalents of Go data models
ui/frontend_files/manifest.json PWA manifest for web app configuration
ui/frontend_files/favicon.* Application icons
configmodels/model_subs_data.go Added K4 SNO and encryption algorithm fields to subscriber override data
configmodels/model_slice_site_info.go Updated UPF field type to use 'any' instead of 'interface{}'
VERSION Version bumped to 2.0.2-dev

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

'gnb-inventory': 'gnbInventory',
'gnb-details': 'gnbInventory', // Same manager for details
'upf-inventory': 'upfInventory',
'subscribers': 'subscribers', // identificador genérico
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spanish comment found in code. The comment "identificador genérico" (generic identifier) should be translated to English for consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +94
// El atributo 'onclick' contiene el nombre de la sección, así que lo usamos como selector.
const navLink = document.querySelector(`.nav-link[onclick="showSection('${section}')"]`);
if (navLink) {
navLink.classList.add('active');
}

// Update app state
app.currentSection = section;

// Load data for the section
this.loadSectionData(section);
}

loadSectionData(section) {
// Lógica para la sección de suscriptores (página original combinada)
if (section === 'subscribers') {
app.managers.k4Manager.loadData();
app.managers.subscriberManager.renderForm();
} else if (section === 'k4-keys') {
// Load K4 keys list
app.managers.k4Manager.loadData();
} else if (section === 'subscribers-list') {
// Load subscribers list
app.managers.subscriberListManager.loadData();
} else if (section === 'device-groups') {
// Load device groups list
const managerKey = this.sections[section];
if (managerKey && app.managers[managerKey]) {
app.managers[managerKey].loadData();
}
} else if (section === 'network-slices') {
// Load network slices list
const managerKey = this.sections[section];
if (managerKey && app.managers[managerKey]) {
app.managers[managerKey].loadData();
}
} else if (section === 'gnb-inventory') {
// Load gNB inventory list
const managerKey = this.sections[section];
if (managerKey && app.managers[managerKey]) {
app.managers[managerKey].loadData();
}
} else if (section === 'device-group-details' || section === 'gnb-details' || section === 'network-slice-details' || section === 'k4-details' || section === 'subscriber-details') {
// Don't reload data for details views as they're already loaded
return;
} else {
const managerKey = this.sections[section];
if (managerKey && app.managers[managerKey]) {
app.managers[managerKey].loadData();
}
}
}
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spanish comments found in code. Comments should be in English for consistency with the rest of the codebase. Lines 43, 57, 85, and others contain Spanish text.

Copilot uses AI. Check for mistakes.
Comment on lines +200 to +202
if (!container) {
return;
}
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixed tabs and spaces detected for indentation. The code uses tabs at the beginning of lines 200-202 while the rest of the file uses spaces. This inconsistency should be fixed to maintain uniform code formatting.

Copilot uses AI. Check for mistakes.
Comment on lines +204 to +246
let html = this.renderListControls();

if (!subscribers || subscribers.length === 0) {
html += `
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>
No subscribers found
</div>
`;
container.innerHTML = html;
this.bindListControls();
return;
}

html += '<div class="table-responsive"><table class="table table-striped">';
html += '<thead><tr><th>UE ID (IMSI)</th><th>PLMN ID</th><th>Actions</th></tr></thead><tbody>';

subscribers.forEach(subscriber => {
const ueId = subscriber.ueId || 'N/A';
const plmnId = subscriber.plmnID || 'N/A';

html += `
<tr class="subscriber-row" onclick="showSubscriberDetails('${ueId}')" style="cursor: pointer;">
<td><strong>${ueId}</strong></td>
<td><code>${plmnId}</code></td>
<td onclick="event.stopPropagation();">
<button class="btn btn-sm btn-outline-primary me-1"
onclick="editItem('${this.type}', '${ueId}')">
<i class="fas fa-edit"></i> Edit
</button>
<button class="btn btn-sm btn-outline-danger"
onclick="deleteItem('${this.type}', '${ueId}')">
<i class="fas fa-trash"></i> Delete
</button>
</td>
</tr>
`;
});


html += '</tbody></table></div>';
container.innerHTML = html;
this.bindListControls();
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixed tabs and spaces detected for indentation. Lines 204-246 use tabs for indentation while the rest of the file uses spaces. This inconsistency should be fixed to maintain uniform code formatting throughout the file.

Copilot uses AI. Check for mistakes.
if err != nil {
return nil, err
}
err = mClient.Client.Disconnect(context.Background())
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mClient may be nil at this dereference because errConnect may not have been checked.

Copilot uses AI. Check for mistakes.
* JavaScript equivalent of Go structs from model_subs_data.go
*/

import { FlowRule } from "./model_flow_rule";
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import FlowRule.

Copilot uses AI. Check for mistakes.
renderEditableDetails(sliceData) {
const siteInfo = sliceData['site-info'] || {};
const plmn = siteInfo.plmn || {};
const gNodeBs = siteInfo.gNodeBs || [];
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable gNodeBs.

Copilot uses AI. Check for mistakes.
const siteInfo = sliceData['site-info'] || {};
const plmn = siteInfo.plmn || {};
const gNodeBs = siteInfo.gNodeBs || [];
const upf = siteInfo.upf || {};
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable upf.

Copilot uses AI. Check for mistakes.
const plmn = siteInfo.plmn || {};
const gNodeBs = siteInfo.gNodeBs || [];
const upf = siteInfo.upf || {};
const deviceGroups = sliceData['site-device-group'] || [];
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable deviceGroups.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +41
RUN go install github.com/go-task/task/v3/cmd/task@latest

WORKDIR $GOPATH/src/webconsole

COPY go.mod .
COPY go.sum .
COPY Taskfile.yml .

RUN task mod-start


COPY . .
RUN make all && \
CGO_ENABLED=0 go build -a -installsuffix nocgo -o webconsole -x server.go

FROM alpine:3.23@sha256:51183f2cfa6320055da30872f211093f9ff1d3cf06f39a0bdb212314c5dc7375 AS webui
ARG BUILD_UI=true
RUN if [ "$BUILD_UI" = "true" ]; then \
task webconsole-ui; \
else \
task all; \
fi
Copy link

Copilot AI Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Dockerfile installs and executes the task build tool via go install github.com/go-task/task/v3/cmd/task@latest, which pulls arbitrary mutable code at build time (@latest) and then runs it as part of the build pipeline. If the upstream module or its supply chain is compromised, an attacker could execute code during image builds with access to build secrets and artifacts. To reduce this risk, pin task to a specific, audited version (e.g., a fixed tag or commit) and treat it as a normal dependency rather than fetching @latest dynamically in the build stage.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings December 31, 2025 03:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 148 out of 155 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

func updateSubscriberInDeviceGroups(imsi string) (int, error) {
func updateSubscriberInDeviceGroupsWhenDeleteSub(imsi string) (int, error) {
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function name is inconsistent with casing conventions. Consider renaming to updateSubscriberInDeviceGroupsWhenDeleteSubscriber or updateSubscriberInDeviceGroupsOnDelete for clarity.

Suggested change
func updateSubscriberInDeviceGroupsWhenDeleteSub(imsi string) (int, error) {
func updateSubscriberInDeviceGroupsWhenDeleteSubscriber(imsi string) (int, error) {

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +59
logger.AppLog.Errorln("K4 Key DeK4DataDelete Error:", err)
return err
}
logger.AppLog.Debugf("successfully processed K4 key DeK4DataDelete for SNO: %s", k4Sno)
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected 'DeK4DataDelete' to 'Delete' in error message.

Suggested change
logger.AppLog.Errorln("K4 Key DeK4DataDelete Error:", err)
return err
}
logger.AppLog.Debugf("successfully processed K4 key DeK4DataDelete for SNO: %s", k4Sno)
logger.AppLog.Errorln("K4 Key Delete Error:", err)
return err
}
logger.AppLog.Debugf("successfully processed K4 key delete for SNO: %s", k4Sno)

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +59
logger.AppLog.Errorln("K4 Key DeK4DataDelete Error:", err)
return err
}
logger.AppLog.Debugf("successfully processed K4 key DeK4DataDelete for SNO: %s", k4Sno)
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected 'DeK4DataDelete' to 'delete' in success message.

Suggested change
logger.AppLog.Errorln("K4 Key DeK4DataDelete Error:", err)
return err
}
logger.AppLog.Debugf("successfully processed K4 key DeK4DataDelete for SNO: %s", k4Sno)
logger.AppLog.Errorln("K4 Key delete Error:", err)
return err
}
logger.AppLog.Debugf("successfully processed K4 key delete for SNO: %s", k4Sno)

Copilot uses AI. Check for mistakes.
this.uplink = 0; // uplink data rate in bps
this.downlink = 0; // downlink data rate in bps
this.bitrateUnit = ""; // data rate unit for uplink and downlink
this.traffiClass = ""; // QCI/QFI for the traffic
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'traffiClass' to 'trafficClass'.

Suggested change
this.traffiClass = ""; // QCI/QFI for the traffic
this.trafficClass = ""; // QCI/QFI for the traffic

Copilot uses AI. Check for mistakes.
return http.StatusBadRequest, err
}

var errorOccured bool
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'errorOccured' to 'errorOccurred'.

Copilot uses AI. Check for mistakes.
Comment on lines +247 to +265
var errorOccured bool
wg := sync.WaitGroup{}

// delete IMSI's that are removed
dimsis := getDeletedImsisList(&deviceGroup, prevDevGroup)
for _, imsi := range dimsis {
wg.Add(1)
go func() {
defer wg.Done()
err := removeSubscriberEntriesRelatedToDeviceGroups(slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc, imsi)
if err != nil {
logger.ConfigLog.Errorln(err)
errorOccured = true
}
}()
}
wg.Wait()

if errorOccured {
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable name should be 'errorOccurred'.

Suggested change
var errorOccured bool
wg := sync.WaitGroup{}
// delete IMSI's that are removed
dimsis := getDeletedImsisList(&deviceGroup, prevDevGroup)
for _, imsi := range dimsis {
wg.Add(1)
go func() {
defer wg.Done()
err := removeSubscriberEntriesRelatedToDeviceGroups(slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc, imsi)
if err != nil {
logger.ConfigLog.Errorln(err)
errorOccured = true
}
}()
}
wg.Wait()
if errorOccured {
var (
errorOccurred bool
mu sync.Mutex
)
wg := sync.WaitGroup{}
// delete IMSI's that are removed
dimsis := getDeletedImsisList(&deviceGroup, prevDevGroup)
for _, imsi := range dimsis {
wg.Add(1)
go func(imsi string) {
defer wg.Done()
err := removeSubscriberEntriesRelatedToDeviceGroups(slice.SiteInfo.Plmn.Mcc, slice.SiteInfo.Plmn.Mnc, imsi)
if err != nil {
logger.ConfigLog.Errorln(err)
mu.Lock()
errorOccurred = true
mu.Unlock()
}
}(imsi)
}
wg.Wait()
mu.Lock()
hasError := errorOccurred
mu.Unlock()
if hasError {

Copilot uses AI. Check for mistakes.
}
wg.Wait()

if errorOccured {
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable name should be 'errorOccurred'.

Copilot uses AI. Check for mistakes.
<div class="card border-success">
<div class="card-body">
<h5 class="card-title">
<i class="fas fa-heartbeat me-2 text-success"></i>Check K4 Life
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term 'K4 Life' is ambiguous. Consider renaming to 'K4 Health Check' or 'K4 Key Lifecycle' for clarity.

Suggested change
<i class="fas fa-heartbeat me-2 text-success"></i>Check K4 Life
<i class="fas fa-heartbeat me-2 text-success"></i>K4 Health Check

Copilot uses AI. Check for mistakes.
dependabot bot and others added 7 commits December 30, 2025 22:48
…o Aether Core.

- API for managing K4 (encryption keys)
- Modules for handling the client and login in both options
- Login to Vault with AppRole, Kubernetes, and certificates
- Optimization of the subscriber synchronization process when a network slice or device group was updated, and also when a subscriber was deleted
- Sync and health check modules for Vault and SSM
- Web UI with vanilla JS
- Implementation of pagination and filtering for the get users endpoint
- Improvements to device group and network slice validations
- Tests for the integrated functionalities
- New models

see info about the ssm here:  https://github.com/networkgcorefullcode/ssm

Signed-off-by: PedroVhGit <pedrovh040110@gmail.com>
- Updated logging calls in `handlers_user_account.go` to replace `logger.DbLog` with `logger.AppLog` for better clarity and consistency.
- Enhanced error handling and logging in user account creation, deletion, and password change functions.

Add slice request parsing and validation helper function

- Introduced `parseAndValidateSliceRequest` function in `slice_helpers.go` to handle JSON binding and validation for network slice requests.
- Implemented comprehensive validation for required fields and application filtering rules within the slice request.

Update tests to reflect changes in logging and slice validation

- Modified test cases in `slice_helpers_batch_test.go` and `slice_operations_test.go` to accommodate new logging structure and slice validation logic.
- Ensured that error messages are consistent with the new validation rules.

Refactor subscriber helpers for improved error logging

- Changed logging in `subscriber_helpers.go` to utilize `logger.AppLog` for all error messages related to subscriber authentication data operations.
- Enhanced rollback error handling during subscriber data updates and deletions.

Clean up unused code and improve readability

- Removed redundant code and comments in `validators.go` related to slice request validation, centralizing the logic in the new helper function.
- Simplified mock structures in `server_test.go` for better clarity and maintainability.

Signed-off-by: PedroVhGit <pedrovh040110@gmail.com>
Signed-off-by: PedroVhGit <pedrovh040110@gmail.com>
- Improved error handling in key rotation and health check functions to return errors from VaultSyncInitDefault.
- Cleaned up code by removing unnecessary blank lines and comments.
- Enhanced logging to provide better insights into failures during Vault operations.
- Updated test cases to ensure proper error handling and response validation.
- Consolidated mutex declarations for better readability.
- Added SPDX license headers to several files for compliance.
- Fixed minor issues in user account handling and subscriber configuration APIs.

Signed-off-by: PedroVhGit <pedrovh040110@gmail.com>
Copy link
Contributor

@gab-arrobo gab-arrobo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @vhPedroGitHub, thanks for your contribution. There are some changes that I think should not be there such as the changes inside the .github directory. It seems that the version of webconsole you are using is a bit old. So, please rebase your PR.

Also, as per the PR description, you mentioned that a (vanilla) UI was added. It would be great to see how it looks like and what capabilities it supports. Would it be possible that you add some screen captures providing details. Also, given that this is a kind of big PR, it would take us some time to go over. So, it would be great if you can attend an Aether TST meeting (next one is this coming Tuesday) for give a talk about the changes. Or we can have a call through Slack (please join the Aether community in Slack)

WebUILog *zap.SugaredLogger
ContextLog *zap.SugaredLogger
GinLog *zap.SugaredLogger
GrpcLog *zap.SugaredLogger
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not using GRPC (for the webconsole) anymore

WebUILog = log.Sugar().With("component", "WebUI", "category", "WebUI")
ContextLog = log.Sugar().With("component", "WebUI", "category", "Context")
GinLog = log.Sugar().With("component", "WebUI", "category", "GIN")
GrpcLog = log.Sugar().With("component", "WebUI", "category", "GRPC")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not using GRPC anymore. Why was it added?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these changes are not correct. It seems to me that you are using an older version of the webconsole. The Latest version has to have the permissions you are removing. Please revert these changes

@gab-arrobo
Copy link
Contributor

@thakurajayL @sureshmarikkannu, any thoughts/comments about this PR?

@gab-arrobo
Copy link
Contributor

Hi @vhPedroGitHub, any update about this PR? Thanks!

@vhPedroGitHub
Copy link
Author

Hi @gab-arrobo . I'm on exams right now; when I finish, I'll answer the comments and update the PR.

@gab-arrobo
Copy link
Contributor

Hi @gab-arrobo . I'm on exams right now; when I finish, I'll answer the comments and update the PR.

@vhPedroGitHub, thanks for the update. Another important aspect would be to break the PR into smaller PRs to make it easier for us to review them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants