Skip to content

Commit 296c4ff

Browse files
committed
Merge branch 'deployment-manager'
2 parents 7a03c39 + b7565a0 commit 296c4ff

File tree

122 files changed

+6902
-1941
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+6902
-1941
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Create and publish Docker image for Deployment manager to ghcr.io
2+
3+
on:
4+
release:
5+
types: ['published']
6+
7+
env:
8+
REGISTRY: ghcr.io
9+
IMAGE_NAME: SAP/deployment-manager
10+
11+
jobs:
12+
build-and-push-image:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
packages: write
17+
attestations: write
18+
id-token: write
19+
20+
environment: ghcr:cloud-active-defense
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Log in to the Container registry
27+
uses: docker/[email protected]
28+
with:
29+
registry: ${{ env.REGISTRY }}
30+
username: ${{ github.actor }}
31+
password: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Extract metadata of deployment manager
34+
id: meta
35+
uses: docker/[email protected]
36+
with:
37+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
38+
39+
- name: Build and push Docker image of cdeployment manager
40+
id: push
41+
uses: docker/[email protected]
42+
with:
43+
context: ./deployment-manager
44+
push: true
45+
file: ./deployment-manager/Dockerfile
46+
tags: ${{ steps.meta.outputs.tags }}
47+
labels: ${{ steps.meta.outputs.labels }}

assets/controlpanel-select-app.png

54.8 KB
Loading
55.1 KB
Loading

controlpanel/api/.env

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ POSTGRES_PASSWORD=postgres
33
DB_HOST=controlpanel-db
44
DB_PORT=5432
55

6-
# Number of minutes
7-
CRON_CONFIGMANAGER=60
8-
96
CONTROLPANEL_FRONTEND_URL=http://localhost:4200
10-
CONFIGMANAGER_URL=http://configmanager:3000
7+
DEPLOYMENT_MANAGER_URL=
8+
9+
DEPLOYMENT_MANAGER_PASSWORD=deployment_manager
10+
11+
ENVOY_API_KEY=F3mTzUj8nRbW4pQc7gHxN1AvD5sL6KfVZ0yPuJkE2R9qXi8MwB7lChGvTa1ZoS3Nd
12+
FLUENTBIT_API_KEY=A7nW2zQj9rMgP4kEmB5vDfL1sY6uHxVqJc0tKbR3wNp8oUiZhXlC2yFoGvTd9Sa8Nm
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const ApiKey = require('../models/Api-key');
2+
3+
const authenticate = async (req, res, next) => {
4+
const key = req.headers['authorization'];
5+
if (!key) {
6+
return res.status(401).json({ type: 'error', code: 401, message: "You must use an API key to access this" });
7+
}
8+
const apiKey = await ApiKey.findOne({ where: { key }})
9+
if (!apiKey) {
10+
return res.status(403).json({ type: 'error', code: 403, message: "Invalid API key" });
11+
}
12+
if (!apiKey.permissions.includes('configmanager') && !apiKey.permissions.includes('admin')) {
13+
return res.status(403).json({ type: 'error', code: 403, message: "You don't have the required permissions to access this" });
14+
}
15+
next();
16+
};
17+
18+
module.exports = authenticate;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const { isUrl } = require('../util/index')
2+
const checkDeploymentManagerURL = (req, res, next) => {
3+
if (!process.env.DEPLOYMENT_MANAGER_URL || !isUrl(process.env.DEPLOYMENT_MANAGER_URL)) {
4+
return res.status(500).json({ type: 'error', code: 500, message: "Deployment manager URL is not configured or badly formatted, you are probably not running Cloud Active Defense in Kyma" });
5+
}
6+
next();
7+
}
8+
9+
module.exports = checkDeploymentManagerURL;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const ApiKey = require('../models/Api-key');
2+
3+
const authenticate = async (req, res, next) => {
4+
const key = req.headers['authorization'];
5+
if (!key) {
6+
return res.status(401).json({ type: 'error', code: 401, message: "You must use an API key to access this" });
7+
}
8+
const apiKey = await ApiKey.findOne({ where: { key }})
9+
if (!apiKey) {
10+
return res.status(403).json({ type: 'error', code: 403, message: "Invalid API key" });
11+
}
12+
if (!apiKey.permissions.includes('fluentbit') && !apiKey.permissions.includes('admin')) {
13+
return res.status(403).json({ type: 'error', code: 403, message: "You don't have the required permissions to access this" });
14+
}
15+
next();
16+
};
17+
18+
module.exports = authenticate;

controlpanel/api/models/Api-key.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const { DataTypes } = require("sequelize")
2+
const sequelize = require("../config/db.config");
3+
const ProtectedApp = require("./ProtectedApp");
4+
5+
const ApiKey = sequelize.define("apiKey", {
6+
id: {
7+
type: DataTypes.UUID,
8+
defaultValue: DataTypes.UUIDV4,
9+
primaryKey: true
10+
},
11+
key: {
12+
type: DataTypes.STRING,
13+
allowNull: false
14+
},
15+
permissions: {
16+
type: DataTypes.ARRAY(DataTypes.STRING),
17+
allowNull: false
18+
},
19+
pa_id: {
20+
type: DataTypes.UUID,
21+
allowNull: false,
22+
references: {
23+
model: ProtectedApp,
24+
key: 'id'
25+
},
26+
},
27+
expirationDate: {
28+
type: DataTypes.DATE,
29+
allowNull: false,
30+
defaultValue: new Date(new Date().setFullYear(new Date().getFullYear() + 1))
31+
}
32+
});
33+
module.exports = ApiKey;

controlpanel/api/models/Customer.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const { DataTypes } = require("sequelize")
2+
const sequelize = require("../config/db.config");
3+
const Sequelize = require("sequelize");
4+
5+
const Customer = sequelize.define("customer", {
6+
id: {
7+
type: DataTypes.UUID,
8+
defaultValue: DataTypes.UUIDV4,
9+
primaryKey: true
10+
},
11+
name: {
12+
type: DataTypes.STRING,
13+
allowNull: false
14+
},
15+
kubeconfig: {
16+
type: DataTypes.TEXT,
17+
allowNull: true
18+
},
19+
});
20+
21+
Customer.getCustomersWithExpiredApiKeys = async () => {
22+
return await Customer.findAll({
23+
include: [{
24+
model: sequelize.models.protectedApp,
25+
as: 'protectedApps',
26+
include: [{
27+
model: sequelize.models.apiKey,
28+
as: 'apiKeys',
29+
where: {
30+
expirationDate: {
31+
[Sequelize.Op.lte]: new Date()
32+
}
33+
},
34+
required: true
35+
}]
36+
}]
37+
});
38+
};
39+
40+
module.exports = Customer;

controlpanel/api/models/ProtectedApp.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { DataTypes } = require("sequelize")
22
const sequelize = require("../config/db.config");
3+
const Customer = require("./Customer");
34

45
const ProtectedApp = sequelize.define("protectedApp", {
56
id: {
@@ -15,5 +16,13 @@ const ProtectedApp = sequelize.define("protectedApp", {
1516
type: DataTypes.STRING,
1617
allowNull: false
1718
},
19+
cu_id: {
20+
type: DataTypes.UUID,
21+
allowNull: false,
22+
references: {
23+
model: Customer,
24+
key: 'id'
25+
},
26+
},
1827
});
1928
module.exports = ProtectedApp;

controlpanel/api/models/index.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
11
const sequelize = require("../config/db.config");
2+
const { QueryTypes } = require("sequelize");
23
const Decoy = require("./Decoy-data");
34
const ProtectedApp = require("./ProtectedApp");
45
const Config = require("./Config-data");
56
const Logs = require("./Logs");
7+
const ApiKey = require("./Api-key");
8+
const Customer = require("./Customer");
69

710
async function initializeDatabase() {
811
await sequelize.sync();
912

1013
try {
1114
await sequelize.authenticate();
15+
const userResult = await sequelize.query(`
16+
SELECT rolname
17+
FROM pg_catalog.pg_roles
18+
WHERE rolname = 'deployment_manager';
19+
`, { type: QueryTypes.SELECT });
20+
if (userResult.length == 0) {
21+
const password = process.env.DEPLOYMENT_MANAGER_PASSWORD || 'deployment_manager';
22+
await sequelize.query(`
23+
CREATE USER deployment_manager WITH PASSWORD :password;
24+
REVOKE ALL ON DATABASE cad FROM deployment_manager;
25+
GRANT CONNECT ON DATABASE cad TO deployment_manager;
26+
GRANT SELECT ON TABLE customers TO deployment_manager;
27+
`, { replacements: { password }});
28+
}
1229
console.log("Database connected successfully.");
1330
} catch (error) {
1431
console.error("Unable to connect to the database...\n", error);
@@ -25,4 +42,10 @@ ProtectedApp.hasMany(Config, {foreignKey: 'pa_id', as: 'configs' });
2542
Logs.belongsTo(ProtectedApp, {foreignKey: 'pa_id', as: 'protectedApps'});
2643
ProtectedApp.hasMany(Logs, {foreignKey: 'pa_id', as: 'logs' });
2744

45+
ApiKey.belongsTo(ProtectedApp, {foreignKey: 'pa_id', as: 'protectedapps'});
46+
ProtectedApp.hasMany(ApiKey, {foreignKey: 'pa_id', as: 'apiKeys' });
47+
48+
ProtectedApp.belongsTo(Customer, {foreignKey: 'cu_id', as: 'customers' });
49+
Customer.hasMany(ProtectedApp, {foreignKey: 'cu_id', as: 'protectedApps' });
50+
2851
module.exports = { sequelize, initializeDatabase };

0 commit comments

Comments
 (0)