Skip to content

Commit

Permalink
✨add synchronization with configmanager
Browse files Browse the repository at this point in the history
  • Loading branch information
TarradeMarc committed Dec 18, 2024
1 parent c7c7c2c commit 66670fa
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 12 deletions.
15 changes: 13 additions & 2 deletions configmanager/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ app.get('/throttlelist', (req, res) => {
})
})
// Start the server
app.listen(3000, () => {
app.listen(3000, async () => {
console.log('Config manager started');
try {
if (!fs.existsSync('/data/cad-default.json')) fs.cpSync('/app/cad-default.json', '/data/cad-default.json');
if (!fs.existsSync('/data/config-default.json')) fs.cpSync('/app/config-default.json', '/data/config-default.json');
Expand All @@ -295,5 +296,15 @@ app.listen(3000, () => {
} catch(e) {
console.error(`Could not create blacklist files: ${e}`);
}
console.log('Config manager started');
loop = 0
while (loop < 5) {
try {
await fetch("http://controlpanel-api:8050/configmanager/sync");
break;
} catch(e) {
loop++;
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait for 5 seconds before retrying
}
}
if (loop == 5) console.log('Cannot connect to api')
});
10 changes: 10 additions & 0 deletions controlpanel/api/routes/configmanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,15 @@ router.put('/config/:namespace/:application', async (req, res) => {
}
})

router.get('/sync', async (req, res) => {
try {
const result = await configmanagerService.sendDataToConfigmanager();
return res.status(result.code).send(result);
} catch(e) {
console.error(e);
return res.status(500).send("Server error");
}
})


module.exports = router;
2 changes: 2 additions & 0 deletions controlpanel/api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const cors = require('cors');
require('dotenv').config({ path: __dirname + '/.env' });
const { CONFIGMANAGER_URL } = require('./util/variables');
const { CONTROLPANEL_URL } = require('./util/variables');
const { sendDataToConfigmanager } = require('./services/configmanager');

const configmanager = require('./routes/configmanager');
const decoys = require('./routes/decoys');
Expand Down Expand Up @@ -39,6 +40,7 @@ app.listen(8050, async () => {
// CONFIGMANAGER URL
await fetch(CONFIGMANAGER_URL);
console.log("Successfully connected to configmanager !")
setInterval(async () => await sendDataToConfigmanager(), 60 * 60 * 1000)
} catch(e) {
console.error("Configmanager is not up, please (re)start configmanager");
}
Expand Down
19 changes: 18 additions & 1 deletion controlpanel/api/services/configmanager.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const { validateDecoyFilter } = require('../util/decoy-validator');
const { validateConfig } = require('../util/config-validator');
const { CONFIGMANAGER_URL } = require('../util/variables');
const ProtectedApp = require('../models/ProtectedApp')
const Config = require('../models/Config-data')
const Decoy = require('../models/Decoy-data')

const axios = require('axios');

Expand Down Expand Up @@ -31,12 +34,13 @@ module.exports = {
* Update decoys list in configmanager
* @param {Object} decoys New list of decoys
*/
updateDecoysList: async (namespace, application, decoys) => {
updateDecoysList: async (namespace, application, decoys) => {
try {
if (!namespace || !application) {
namespace = 'unknown';
application = 'unknown';
}
if (!decoys.length) return { type: 'warning', code: 200, message: "Decoys list is empty or full of inactive decoy, cannot sync" };
for (const decoy of decoys) {
if (validateDecoyFilter(decoy).length) return { type: 'error', code: 422, message: "There are errors in one of the decoys, cannot send to configmanager" }
}
Expand Down Expand Up @@ -103,4 +107,17 @@ module.exports = {
throw e;
}
},

sendDataToConfigmanager: async () => {
try {
const protectedApps = await ProtectedApp.findAll({ include: [{ model: Decoy, as: 'decoys', attributes: ['decoy', 'state'] }, { model: Config, as: 'configs', attributes: ['config'] }] })
for (const pa of protectedApps) {
module.exports.updateDecoysList(pa.namespace, pa.application, pa.decoys.map(decoyData => decoyData.state == 'active' && decoyData.decoy))
module.exports.updateConfig(pa.namespace, pa.application, pa.configs);
}
return { type: 'success', message: "Successful operation", code: 200 };
} catch(e) {
return { type: 'error', message: "Server error", data: e, code: 500 };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ <h1>Config 🔧</h1>
<div class="file-preview">{{ config | json }}</div>
<div class="next">
<button class="filled-btn" (click)="save()">Save</button>
<button class="filled-btn" (click)="sync()">Sync</button>
</div>
</div>
</div>
9 changes: 8 additions & 1 deletion controlpanel/cad/src/app/pages/config/config.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ConfigService } from '../../services/config.service';
import { GlobalStateService } from '../../services/global-state.service';
import { ToastrService } from 'ngx-toastr';
import { isEmptyObject } from '../../utils';
import { ConfigmanagerApiService } from '../../services/api/configmanager-api.service';

@Component({
selector: 'app-config',
Expand Down Expand Up @@ -61,7 +62,7 @@ onLeaveInfo() {
}
//#endregion

constructor(private configService: ConfigService, private globalState: GlobalStateService, private toastr: ToastrService) {
constructor(private configService: ConfigService, private globalState: GlobalStateService, private toastr: ToastrService, private configmanagerApi: ConfigmanagerApiService) {
this.configForm = new FormGroup({
sessionIn: new FormControl(''),
sessionKey: new FormControl(''),
Expand Down Expand Up @@ -276,4 +277,10 @@ onLeaveInfo() {
if (apiResponse.type == 'error') this.toastr.error(apiResponse.message, "Error when saving global config");
else this.toastr.success(apiResponse.message, 'Successfully updated global config');
}
async sync() {
const saveResponse = await this.configmanagerApi.updateConfigmanagerConfig(this.globalState.selectedApp.namespace, this.globalState.selectedApp.application, this.config)
if (saveResponse.type == 'error') this.toastr.error(saveResponse.message, "Error Synchronizing");
else if (saveResponse.type == 'warning') this.toastr.warning(saveResponse.message, "Warning");
else this.toastr.success("Successfully synchronized with configmanager", "Synchronized");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ <h1>Decoys list 🗒️</h1>
</tbody>
</table>
<div class="buttons">
<!-- <button class="filled-btn" (click)="save()">Save</button> -->
<button class="filled-btn" (click)="save()">Sync</button>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { isProtectedAppEmpty } from '../../models/protected-app';
import { RouterLink } from '@angular/router';
import { UUID } from '../../models/types';
import { Subscription } from 'rxjs';
import { ConfigmanagerApiService } from '../../services/api/configmanager-api.service';

@Component({
selector: 'app-list-decoy',
Expand All @@ -22,7 +23,7 @@ export class ListDecoyComponent implements OnInit, OnDestroy {
decoys: DecoyData[] = [];
globalStateSubscription?: Subscription;

constructor(private decoyService: DecoyService, private toastr: ToastrService, private globalState: GlobalStateService) { }
constructor(private decoyService: DecoyService, private toastr: ToastrService, private globalState: GlobalStateService, private configmanagerApi: ConfigmanagerApiService) { }

async ngOnInit() {
this.globalStateSubscription = this.globalState.selectedApp$.subscribe(data => {
Expand Down Expand Up @@ -68,10 +69,11 @@ export class ListDecoyComponent implements OnInit, OnDestroy {
}
}

// async save() {
// if (!this.decoys.length) return;
// const saveResponse = await this.decoyService.updateDecoysState(this.decoys);
// if (saveResponse.type == 'error') this.toastr.error(saveResponse.message, "Error saving");
// else this.toastr.success("Successfully saved decoys states", "Saved");
// }
async save() {
if (!this.decoys.length) return;
const saveResponse = await this.configmanagerApi.updateConfigmanagerDecoys(this.globalState.selectedApp.namespace, this.globalState.selectedApp.application, this.decoys.filter(decoyData => decoyData.state == 'active').map(decoyData => decoyData.decoy))
if (saveResponse.type == 'error') this.toastr.error(saveResponse.message, "Error Synchronizing");
else if (saveResponse.type == 'warning') this.toastr.warning(saveResponse.message, "Warning");
else this.toastr.success("Successfully synchronized with configmanager", "Synchronized");
}
}
41 changes: 41 additions & 0 deletions controlpanel/cad/src/app/services/api/configmanager-api.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { lastValueFrom } from 'rxjs';
import { ApiResponse } from '../../models/api-response';
import { GlobalStateService } from '../global-state.service';
import { Decoy } from '../../models/decoy';
import { Config } from '../../models/config';

@Injectable({
providedIn: 'root'
})
export class ConfigmanagerApiService {

constructor(private http: HttpClient, private globalState: GlobalStateService) { }

async updateConfigmanagerDecoys(namespace: string, application: string, decoys: Decoy[]) {
try {
return await lastValueFrom(this.http.put<ApiResponse>(`${this.globalState.API_URL}/configmanager/decoys/${namespace}/${application}`, decoys));
} catch (e) {
console.error(e);
return { message: 'Cannot synchronize decoys with configmanager', type: 'error' };
}
}
async updateConfigmanagerConfig(namespace: string, application: string, config: Config) {
try {
return await lastValueFrom(this.http.put<ApiResponse>(`${this.globalState.API_URL}/configmanager/config/${namespace}/${application}`, config));
} catch (e) {
console.error(e);
return { message: 'Cannot synchronize config with configmanager', type: 'error' };
}
}
async getConfigmanagerDecoys(namespace: string, application: string) {
try {
return await lastValueFrom(this.http.get<ApiResponse>(`${this.globalState.API_URL}/configmanager/decoys/${namespace}/${application}`));
} catch (e) {
console.error(e);
return { message: 'Cannot synchronize config with configmanager', type: 'error' };
}
}

}

0 comments on commit 66670fa

Please # to comment.