Initial Commit

Change-Id: Iec38321b67ec1171d492b31b43ffed58ffabcbb2
This commit is contained in:
George Kitsos 2024-03-15 13:29:55 +02:00 committed by jmarchel
parent 9b05f5d222
commit ac23039c0d
56 changed files with 2571 additions and 116 deletions

View File

@ -22,3 +22,8 @@ version: 0.1.0
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "latest"
dependencies:
- name: postgresql
version: 14.3.3
repository: https://charts.bitnami.com/bitnami

View File

@ -27,6 +27,10 @@ spec:
serviceAccountName: {{ include "nebulous-overlay-network-manager.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: wait-for-postgresql
image: docker.io/bitnami/postgresql:14.3.0
command: ['sh', '-c', 'until pg_isready -h nebulous-overlay-network-manager-postgresql -p 5432; do echo waiting for database; sleep 2; done;']
containers:
- name: {{ .Chart.Name }}
securityContext:
@ -34,19 +38,33 @@ spec:
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
- name: onm-api
containerPort: 8082
protocol: TCP
- name: pgadmin
containerPort: 5050
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
- name: POSTGRES_USER
value: {{ .Values.postgresql.global.postgresql.auth.username }}
- name: POSTGRES_PASSWORD
value: {{ .Values.postgresql.global.postgresql.auth.password }}
- name: POSTGRES_DB
value: {{ .Values.postgresql.global.postgresql.auth.database }}
- name: POSTGRES_IP_FQDN
value: "nebulous-overlay-network-manager-postgresql"
- name: POSTGRES_CONNECTION_STRING
value: "jdbc:postgresql://nebulous-overlay-network-manager-postgresql:5432/postgres"
- name: WIREGUARD_NETWORK_PORTION
value: "{{ .Values.customEnv.WIREGUARD_NETWORK_PORTION }}"
- name: WIREGUARD_DEFAULT_SERVER_IP
value: "{{ .Values.customEnv.WIREGUARD_DEFAULT_SERVER_IP }}"
- name: WIREGUARD_ALLOWED_IPS
value: "{{ .Values.customEnv.WIREGUARD_ALLOWED_IPS }}"
- name: _PROD_WG_BOOTSTRAP_AGENT_SCRIPTS_DIR
value: "{{ .Values.customEnv._PROD_WG_BOOTSTRAP_AGENT_SCRIPTS_DIR }}"
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}

View File

@ -7,9 +7,13 @@ metadata:
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
- port: {{ .Values.service.pgadminPort }}
targetPort: pgadmin
protocol: TCP
name: http
name: pgadmin
- port: {{ .Values.service.onmApiPort }}
targetPort: onm-api
protocol: TCP
name: onm-api
selector:
{{- include "nebulous-overlay-network-manager.selectorLabels" . | nindent 4 }}

View File

@ -5,7 +5,7 @@
replicaCount: 1
image:
repository: "quay.io/nebulous/overlay-network-manager-java-spring-boot-demo"
repository: "quay.io/nebulous/overlay-network-manager"
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
@ -39,6 +39,8 @@ securityContext: {}
service:
type: ClusterIP
port: 80
pgadminPort: 5050
onmApiPort: 8082
ingress:
enabled: false
@ -80,3 +82,18 @@ nodeSelector: {}
tolerations: []
affinity: {}
postgresql:
global:
postgresql:
auth:
postgresPassword: "nebulous"
username: "postgresql"
password: "postgresql"
database: "postgres"
customEnv:
WIREGUARD_NETWORK_PORTION: "192.168.55."
WIREGUARD_DEFAULT_SERVER_IP: "192.168.55.1"
WIREGUARD_ALLOWED_IPS: "192.168.55.0/24"
_PROD_WG_BOOTSTRAP_AGENT_SCRIPTS_DIR: "/deployments/wg-bootstrap-agent-scripts"

View File

@ -1,15 +0,0 @@
#
# Build stage
#
FROM docker.io/library/maven:3.9.2-eclipse-temurin-17 AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package
#
# Package stage
#
FROM docker.io/library/eclipse-temurin:17-jre
COPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/usr/local/lib/demo.jar"]

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,13 +0,0 @@
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

View File

@ -1,14 +0,0 @@
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@RequestMapping("/")
public Object root() {
return null;
}
}

View File

@ -1,13 +0,0 @@
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,11 @@
PC_IP_ADDRESS=
POSTGRES_CONNECTION_STRING=
POSTGRES_USER=
POSTGRES_PASSWORD=
WIREGUARD_NETWORK_PORTION=
WIREGUARD_DEFAULT_SERVER_IP=
WIREGUARD_ALLOWED_IPS=
_DEV_WG_BOOTSTRAP_AGENT_SCRIPTS_DIR=
_PROD_WG_BOOTSTRAP_AGENT_SCRIPTS_DIR=

View File

@ -31,3 +31,6 @@ build/
### VS Code ###
.vscode/
# Local environment
.env

View File

@ -0,0 +1,18 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>quarkus-base-no-auth</id>
<configuration>
<httpHeaders>
<property>
<name>Job-Token</name>
<value>${CI_JOB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>

View File

@ -0,0 +1 @@
maven-wrapper.jar

View File

@ -0,0 +1,142 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader
{
private static final String WRAPPER_VERSION = "3.1.1";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/" + WRAPPER_VERSION
+ "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to use instead of the
* default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main( String args[] )
{
System.out.println( "- Downloader started" );
File baseDirectory = new File( args[0] );
System.out.println( "- Using base directory: " + baseDirectory.getAbsolutePath() );
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File( baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH );
String url = DEFAULT_DOWNLOAD_URL;
if ( mavenWrapperPropertyFile.exists() )
{
FileInputStream mavenWrapperPropertyFileInputStream = null;
try
{
mavenWrapperPropertyFileInputStream = new FileInputStream( mavenWrapperPropertyFile );
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load( mavenWrapperPropertyFileInputStream );
url = mavenWrapperProperties.getProperty( PROPERTY_NAME_WRAPPER_URL, url );
}
catch ( IOException e )
{
System.out.println( "- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'" );
}
finally
{
try
{
if ( mavenWrapperPropertyFileInputStream != null )
{
mavenWrapperPropertyFileInputStream.close();
}
}
catch ( IOException e )
{
// Ignore ...
}
}
}
System.out.println( "- Downloading from: " + url );
File outputFile = new File( baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH );
if ( !outputFile.getParentFile().exists() )
{
if ( !outputFile.getParentFile().mkdirs() )
{
System.out.println( "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath()
+ "'" );
}
}
System.out.println( "- Downloading to: " + outputFile.getAbsolutePath() );
try
{
downloadFileFromURL( url, outputFile );
System.out.println( "Done" );
System.exit( 0 );
}
catch ( Throwable e )
{
System.out.println( "- Error downloading" );
e.printStackTrace();
System.exit( 1 );
}
}
private static void downloadFileFromURL( String urlString, File destination )
throws Exception
{
if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null )
{
String username = System.getenv( "MVNW_USERNAME" );
char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray();
Authenticator.setDefault( new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication( username, password );
}
} );
}
URL website = new URL( urlString );
ReadableByteChannel rbc;
rbc = Channels.newChannel( website.openStream() );
FileOutputStream fos = new FileOutputStream( destination );
fos.getChannel().transferFrom( rbc, 0, Long.MAX_VALUE );
fos.close();
rbc.close();
}
}

View File

@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar

View File

@ -0,0 +1,43 @@
FROM docker.io/curlimages/curl:8.5.0 AS downloader
ARG RUN_JAVA_VERSION=1.3.5
RUN curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /tmp/run-java.sh
FROM docker.io/maven:3.9.1-eclipse-temurin-20 AS build
WORKDIR /app
COPY src ./src
COPY wg-bootstrap-agent-scripts ./wg-bootstrap-agent-scripts
COPY pom.xml ./
RUN mvn clean package -DskipTests
FROM docker.io/eclipse-temurin:20-jre-alpine
ENV USER_ID=1001
RUN mkdir /deployments \
&& chown ${USER_ID} /deployments \
&& chmod "g+rwX" /deployments \
&& chown 1001:root /deployments
COPY --from=downloader /tmp/run-java.sh /deployments/run-java.sh
RUN chown ${USER_ID} /deployments/run-java.sh && chmod 540 /deployments/run-java.sh
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
ENV JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8090"
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
# Copy the built artifact from the maven image
COPY --from=build /app/target/*-runner.jar /deployments/app.jar
# Copy scripts from build Dockerfile step
COPY --from=build /app/wg-bootstrap-agent-scripts /deployments/wg-bootstrap-agent-scripts
EXPOSE 8080
EXPOSE 8090
USER ${USER_ID}
ENTRYPOINT [ "/deployments/run-java.sh" ]

85
network-manager/README.md Normal file
View File

@ -0,0 +1,85 @@
# Overlay Network Manager
## Provided Services
This is a template project, providing the bare minimum in order to build a Quarkus Service.
To be more precise, it includes:
1. Swagger UI with OpenAPI Specification
## Technology Stack
This project uses Quarkus, the Supersonic Subatomic Java Framework.
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/.
Moreover, the core services used, alongside with their versions, are:
1. Quarkus **3.2.7.Final**
2. Java **20**
## Environmental Variables
There is a .env.example file containing all the appropriate information.
## Swagger/OpenAPI Services
These are accessible through the following paths:
1. Swagger UI: http://localhost:8080/api/swagger
2. OpenAPI Specification: http://localhost:8080/api/openapi
## Running the application in dev mode
You can run your application in dev mode that enables live coding using:
```shell script
./mvnw compile quarkus:dev
```
> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
## Packaging and running the application
The application can be packaged using:
```shell script
./mvnw package
```
It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory.
Be aware that its not a _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory.
The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`.
If you want to build a _über-jar_, execute the following command:
```shell script
./mvnw package -Dquarkus.package.type=uber-jar
```
The application, packaged as a _über-jar_, is now runnable using `java -jar target/*-runner.jar`.
## Creating a native executable
You can create a native executable using:
```shell script
./mvnw package -Pnative
```
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
```shell script
./mvnw package -Pnative -Dquarkus.native.container-build=true
```
You can then execute your native executable with: `./target/getting-started-1.0.0-SNAPSHOT-runner`
If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.
Run the docker image using:
```shell script
docker run -i --env-file .env --rm -p 8080:8080 <docker-image-name>
```
## Related Guides
- RESTEasy Reactive ([guide](https://quarkus.io/guides/resteasy-reactive)): A JAX-RS implementation utilizing build time processing and Vert.x. This extension is not compatible with the quarkus-resteasy extension, or any of the extensions that depend on it.
## Provided Code
### RESTEasy Reactive
Easily start your Reactive RESTful Web Services
[Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources)

View File

@ -0,0 +1,52 @@
#!/bin/sh
# Define the original and the copy paths for the kubeconfig file
ORIGINAL_KUBECONFIG_PATH="$HOME/.kube/config"
KUBECONFIG_COPY_PATH="$HOME/.kube/config-copy"
# Copy the original kubeconfig file to a new location
if [ -f "$ORIGINAL_KUBECONFIG_PATH" ]; then
cp "$ORIGINAL_KUBECONFIG_PATH" "$KUBECONFIG_COPY_PATH"
echo "Kubeconfig file copied to $KUBECONFIG_COPY_PATH."
else
echo "Original kubeconfig file not found at $ORIGINAL_KUBECONFIG_PATH."
exit 1
fi
# Create the configmap from the copied kubeconfig file
kubectl create configmap kubeconfig --from-file=config=$KUBECONFIG_COPY_PATH
if [ $? -eq 0 ]; then
echo "ConfigMap created successfully."
else
echo "Failed to create ConfigMap."
exit 1
fi
# Directory to store the YAML files
REPO_URL="https://gitlab.ubitech.eu/nebulous/use-cases/k8s-gatekeeper/-/raw/origin/config"
# Create the directory if it doesn't exist
CONFIG_DIR=$HOME/k8s/config
mkdir -p $CONFIG_DIR
# List of configuration files to download
CONFIG_FILES="rbac.yaml webhook_deployment.yaml webhook_internal.yaml auth.casbin.org_casbinmodels.yaml auth.casbin.org_casbinpolicies.yaml"
# Download the configuration files
for file in $CONFIG_FILES; do
echo "WGET file: $file"
wget -O "$CONFIG_DIR/$file" "$REPO_URL/$file"
if [ $? -ne 0 ]; then
echo "Failed to download $file."
exit 1
fi
done
# apply the downloaded configurations with delay
DELAY=5
for file in $CONFIG_FILES; do
kubectl apply -f "$CONFIG_DIR/$file"
sleep $DELAY
done
echo "All configurations applied successfully."

View File

@ -0,0 +1,70 @@
#!/bin/sh
# Capture the second argument as the hostname
HOSTNAME=$1
# Set the hostname
echo "Setting hostname to '$HOSTNAME'..."
sudo hostnamectl set-hostname "$HOSTNAME"
WIREGUARD_VPN_IP=`ip a | grep wg | grep inet | awk '{print $2}' | cut -d'/' -f1`
# Create k8s directory to host all appropriate files
mkdir -p $HOME/k8s
# Update Repository
sudo DEBIAN_FRONTEND=noninteractive apt update
# Install libraries
sudo DEBIAN_FRONTEND=noninteractive apt install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# Docker Keys
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --yes --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Update Repositories again
sudo DEBIAN_FRONTEND=noninteractive apt update
# Install Docker
sudo DEBIAN_FRONTEND=noninteractive apt install -y docker-ce=5:20.10.22~3-0~ubuntu-jammy docker-ce-cli=5:20.10.22~3-0~ubuntu-jammy containerd.io=1.6.14-1
sudo usermod -aG docker $USER
sudo systemctl enable docker
sudo systemctl start docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl restart docker
# Kubernetes Keys
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --yes --dearmor -o /usr/share/keyrings/google-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-archive-keyring.gpg] http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null
# Update Repositories
sudo DEBIAN_FRONTEND=noninteractive apt-get update
# Install K8s CLI tools
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y kubeadm=1.22.4-00 kubelet=1.22.4-00 kubectl=1.22.4-00
sudo DEBIAN_FRONTEND=noninteractive apt-mark hold kubeadm kubelet kubectl
echo "KUBELET_EXTRA_ARGS=--node-ip=${WIREGUARD_VPN_IP}" | sudo tee -a /etc/default/kubelet
sudo systemctl restart kubelet
# Disable Swap
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# Set hostname label to K8s Node
sudo kubectl label nodes "$HOSTNAME" disktype=ssd
# Install Helm Package Manager
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
sudo chmod 700 get_helm.sh
sudo $HOME/get_helm.sh
echo "Configuration complete."

View File

@ -0,0 +1,27 @@
#!/bin/sh
WIREGUARD_VPN_IP=`ip a | grep wg | grep inet | awk '{print $2}' | cut -d'/' -f1`
# Init kubernetes
sudo kubeadm init --apiserver-advertise-address ${WIREGUARD_VPN_IP} --service-cidr 10.96.0.0/16 --pod-network-cidr 10.244.0.0/16
# Set kubeconfig file
mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# Add Cilium Helm Repo
helm repo add cilium https://helm.cilium.io/
helm repo update
# Install Cilium with Wireguard parameters
helm install cilium cilium/cilium --namespace kube-system --set encryption.enabled=true --set encryption.type=wireguard
# Add KubeVela Helm repository and update
echo "Setting up KubeVela..."
helm repo add kubevela https://kubevelacharts.oss-cn-hangzhou.aliyuncs.com/core
helm repo update
helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wait
# Save join command to specific path for the worker nodes to SCP
kubeadm token create --print-join-command > $HOME/k8s-join-command.sh

View File

@ -0,0 +1,11 @@
#!/bin/sh
MASTER_IP=$1
MASTER_USERNAME=$2
# Join Kubernetes Cluster
sudo scp -o StrictHostKeyChecking=no -i $HOME/wg-private-key.key $MASTER_USERNAME@$MASTER_IP:/home/$MASTER_USERNAME/k8s-join-command.sh /home/$USER/k8s/k8s-join-command.sh
sudo chmod +x $HOME/k8s/k8s-join-command.sh
sudo $HOME/k8s/k8s-join-command.sh

316
network-manager/mvnw vendored Executable file
View File

@ -0,0 +1,316 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

188
network-manager/mvnw.cmd vendored Normal file
View File

@ -0,0 +1,188 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

210
network-manager/pom.xml Normal file
View File

@ -0,0 +1,210 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>eu.nebulous</groupId>
<artifactId>network-manager</artifactId>
<version>1.0.0</version>
<properties>
<!-- Core Properties -->
<compiler-plugin.version>3.11.0</compiler-plugin.version>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.2.7.Final</quarkus.platform.version>
<!-- Skip Integration Tests Flag -->
<skipITs>true</skipITs>
<!-- Surefire Plugin Version -->
<surefire-plugin.version>3.0.0</surefire-plugin.version>
<!-- QPID JMS Properties -->
<quarkus.qpid.jms.group-id>${quarkus.platform.group-id}</quarkus.qpid.jms.group-id>
<quarkus.qpid.jms.version>${quarkus.platform.version}</quarkus.qpid.jms.version>
<!-- Lombok Version -->
<lombok.version>1.18.24</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>${quarkus.qpid.jms.group-id}</groupId>
<artifactId>quarkus-qpid-jms-bom</artifactId>
<version>${quarkus.qpid.jms.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<!-- Quarkus Test -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<!-- Smallrye -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<!-- JSON Parser -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- Application File in YAML Format -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-config-yaml</artifactId>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<!-- BouncyCastle -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.76</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Java SSH Remote Command Execution -->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-common</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-scp</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<skipITs>false</skipITs>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,31 @@
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import io.quarkus.runtime.configuration.ProfileManager;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import java.time.ZoneId;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
@ApplicationScoped
public class Application {
private static final Logger logger = Logger.getLogger(Application.class.getName());
public Application() {
// Empty Constructor
}
void onStart(@Observes StartupEvent ev) {
logger.info("The application is starting...");
logger.log(Level.INFO,"Default timezone: {0} with id {1}", new Object[]{TimeZone.getDefault().getDisplayName(), ZoneId.systemDefault()});
var profile = ProfileManager.getLaunchMode();
logger.log(Level.INFO,"Running profile: {0}", profile);
}
void onStop(@Observes ShutdownEvent ev) {
logger.info("The application is stopping...");
}
}

View File

@ -0,0 +1,10 @@
package eu.nebulous.dto;
public record ApplicationNodeDto(
String publicIp,
String applicationUUID,
Boolean isMaster,
String sshUsername,
String privateKeyBase64,
String publicKey
) {}

View File

@ -0,0 +1,20 @@
package eu.nebulous.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.logging.Level;
@EqualsAndHashCode(callSuper = false)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LogDto {
private Date date;
private Level logLevel;
private String title;
private String message;
}

View File

@ -0,0 +1,16 @@
package eu.nebulous.enums;
public enum StatusEnum {
SUCCESS("Success"),
FAILURE("Failure");
private final String description;
StatusEnum(String description) {
this.description = description;
}
public String getDescription() {
return this.description;
}
}

View File

@ -0,0 +1,17 @@
package eu.nebulous.exception;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response;
import java.io.Serial;
import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
public class BadRequestAlertException extends WebApplicationException {
@Serial
private static final long serialVersionUID = 1L;
public BadRequestAlertException(String message, String entityName, String errorKey) {
super(Response.status(BAD_REQUEST).entity(message).header("message", "error." + errorKey).header("params", entityName).build());
}
}

View File

@ -0,0 +1,19 @@
package eu.nebulous.exception;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response;
import java.io.Serial;
public class InternalServerErrorException extends WebApplicationException {
@Serial
private static final long serialVersionUID = 1L;
public InternalServerErrorException() {
this("HTTP 500 - Internal server error. Please contact site admin.");
}
public InternalServerErrorException(String message) {
super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).build());
}
}

View File

@ -0,0 +1,19 @@
package eu.nebulous.exception;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response;
import java.io.Serial;
import static jakarta.ws.rs.core.Response.Status.NOT_FOUND;
public class NotFoundAlertException extends WebApplicationException {
@Serial
private static final long serialVersionUID = 1L;
public NotFoundAlertException(String entityName) {
super(Response.status(NOT_FOUND).entity("Entity " + entityName + "was not found")
.header("message", "error." + "notfound")
.header("params", entityName).build());
}
}

View File

@ -0,0 +1,50 @@
package eu.nebulous.model;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Date;
@Entity
@EqualsAndHashCode(callSuper = false)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApplicationMasterNode extends PanacheEntity {
private String uuid;
@Column(name = "publicIp")
private String publicIp;
@Column(name = "applicationUUID")
private String applicationUUID;
@Column(name = "sshUsername")
private String sshUsername;
@Column(length = 5000, name = "openSSLPrivateKey")
private String openSSLPrivateKey;
@Column(length = 1000, name = "openSSLPublicKey")
private String openSSLPublicKey;
@Column(name = "wireguardPrivateKey")
private String wireguardPrivateKey;
@Column(name = "wireguardPublicKey")
private String wireguardPublicKey;
@Column(name = "wireguardOverlaySubnet")
private String wireguardOverlaySubnet;
@Column(name = "wireguardIp")
private String wireguardIp;
@Column(name = "dateCreated")
private Date dateCreated;
}

View File

@ -0,0 +1,48 @@
package eu.nebulous.model;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Date;
@Entity
@EqualsAndHashCode(callSuper = false)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApplicationWorkerNode extends PanacheEntity {
private String uuid;
@Column(name = "publicIp")
private String publicIp;
@Column(name = "sshUsername")
private String sshUsername;
@Column(name = "wireguardPrivateKey")
private String wireguardPrivateKey;
@Column(name = "wireguardPublicKey")
private String wireguardPublicKey;
@Column(length = 5000, name = "openSSLPrivateKey")
private String openSSLPrivateKey;
@Column(length = 1000, name = "openSSLPublicKey")
private String openSSLPublicKey;
@Column(name = "dateCreated")
private Date dateCreated;
@Column(name = "wireguardIp")
private String wireguardIp;
@ManyToOne
public ApplicationMasterNode applicationMasterNode;
}

View File

@ -0,0 +1,13 @@
package eu.nebulous.repository;
import eu.nebulous.model.ApplicationMasterNode;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class ApplicationMasterNodeRepository implements PanacheRepository<ApplicationMasterNode> {
public ApplicationMasterNode findByApplicationUUID(String applicationUUID){
return find("applicationUUID", applicationUUID).firstResult();
}
}

View File

@ -0,0 +1,20 @@
package eu.nebulous.repository;
import eu.nebulous.dto.ApplicationNodeDto;
import eu.nebulous.model.ApplicationMasterNode;
import eu.nebulous.model.ApplicationWorkerNode;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.List;
@ApplicationScoped
public class ApplicationWorkerNodeRepository implements PanacheRepository<ApplicationWorkerNode> {
public List<ApplicationWorkerNode> findWorkerNodesByMasterNode(ApplicationMasterNode masterNode){
return find("applicationMasterNode", masterNode).list();
}
public ApplicationWorkerNode findWorkerByPublicIp(ApplicationNodeDto applicationNodeDto){
return find("publicIp", applicationNodeDto.publicIp()).firstResult();
}
}

View File

@ -0,0 +1,20 @@
package eu.nebulous.resource;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Path;
@Singleton
public class ApiResource {
private final ApplicationNodeResource applicationNodeResource;
@Inject
public ApiResource(ApplicationNodeResource applicationNodeResource) {
this.applicationNodeResource = applicationNodeResource;
}
@Path("/node")
public ApplicationNodeResource getAuthResource() {
return applicationNodeResource;
}
}

View File

@ -0,0 +1,46 @@
package eu.nebulous.resource;
import eu.nebulous.dto.ApplicationNodeDto;
import eu.nebulous.service.ApplicationNodeService;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
@Singleton
public class ApplicationNodeResource {
@Inject
ApplicationNodeService applicationNodeService;
@POST
@Path("/create")
@Tag(name = "Application Node")
@Consumes(MediaType.APPLICATION_JSON)
@Operation(summary = "Add Application Node to Application Cluster")
public Response addApplicationNode(@Valid ApplicationNodeDto applicationNodeDto) {
// Create Configuration for Application Node
var logs = applicationNodeService.evaluateNodeCreation(applicationNodeDto);
return Response.ok(logs).build();
}
@DELETE
@Path("/delete")
@Tag(name = "Application Node")
@Consumes(MediaType.APPLICATION_JSON)
@Operation(summary = "Delete Application Node From Application Cluster")
public Response deleteApplicationNode(@Valid ApplicationNodeDto applicationNodeDto) {
// Create Configuration for Application Node
var logs = applicationNodeService.evaluateNodeDeletion(applicationNodeDto);
return Response.ok(logs).build();
}
}

View File

@ -0,0 +1,19 @@
package eu.nebulous.resource;
import jakarta.inject.Inject;
import jakarta.ws.rs.Path;
@Path("/")
public class GatewayResource {
private final ApiResource apiResource;
@Inject
public GatewayResource(ApiResource apiResource) {
this.apiResource = apiResource;
}
@Path("/api/v1")
public ApiResource getApiResource() {
return apiResource;
}
}

View File

@ -0,0 +1,289 @@
package eu.nebulous.service;
import eu.nebulous.dto.ApplicationNodeDto;
import eu.nebulous.dto.LogDto;
import eu.nebulous.model.ApplicationMasterNode;
import eu.nebulous.model.ApplicationWorkerNode;
import eu.nebulous.repository.ApplicationMasterNodeRepository;
import eu.nebulous.repository.ApplicationWorkerNodeRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
@ApplicationScoped
public class ApplicationNodeService {
@Inject
ApplicationMasterNodeRepository applicationMasterNodeRepository;
@Inject
ApplicationWorkerNodeRepository applicationWorkerNodeRepository;
@Inject
WGKeyPairGeneratorService wgKeyPairGeneratorService;
@Inject
RemoteCodeExecutionService remoteCodeExecutionService;
@Inject
LogService logService;
@ConfigProperty(name = "WIREGUARD_ALLOWED_IPS")
String wireguardAllowedIps;
@ConfigProperty(name = "WIREGUARD_DEFAULT_SERVER_IP")
String wireguardDefaultServerIp;
@ConfigProperty(name = "WIREGUARD_NETWORK_PORTION")
String wireguardNetworkPortion;
@ConfigProperty(name = "WG_BOOTSTRAP_AGENT_SCRIPTS_DIR")
String wgBootstrapAgentScriptsDir;
private static final String ONM = "ONM";
private void persistApplicationMasterNode(List<LogDto> logList, ApplicationNodeDto applicationNodeDto, String openSSLPrivateKey, String openSSLPublicKey,
String wireguardPrivateKey, String wireguardPublicKey) {
try {
var applicationMasterNode = new ApplicationMasterNode();
applicationMasterNode.setUuid(UUID.randomUUID().toString());
applicationMasterNode.setPublicIp(applicationNodeDto.publicIp());
applicationMasterNode.setApplicationUUID(applicationNodeDto.applicationUUID());
applicationMasterNode.setSshUsername(applicationNodeDto.sshUsername());
applicationMasterNode.setDateCreated(new Date());
applicationMasterNode.setOpenSSLPrivateKey(openSSLPrivateKey);
applicationMasterNode.setOpenSSLPublicKey(openSSLPublicKey);
applicationMasterNode.setWireguardPrivateKey(wireguardPrivateKey);
applicationMasterNode.setWireguardPublicKey(wireguardPublicKey);
applicationMasterNode.setWireguardOverlaySubnet(wireguardAllowedIps);
applicationMasterNode.setWireguardIp(wireguardDefaultServerIp);
applicationMasterNodeRepository.persist(applicationMasterNode);
logService.log(logList, Level.INFO, ONM, "SUCCESS -> Application Node Master (" + applicationNodeDto.publicIp() +
"," + applicationNodeDto.applicationUUID() + ") successfully persisted to DB!");
} catch (Exception e) {
logService.log(logList, Level.WARNING, ONM, "FAILURE -> The Application Node Master (" + applicationNodeDto.publicIp() +
"," + applicationNodeDto.applicationUUID() + ") failed to be persisted to DB!");
}
}
private void persistApplicationWorkerNode(List<LogDto> logList, ApplicationNodeDto applicationNodeDto, ApplicationMasterNode masterNode,
String wireguardPrivateKey, String wireguardPublicKey, String wireguardWorkerIp) {
try {
var applicationWorkerNode = new ApplicationWorkerNode();
applicationWorkerNode.setUuid(UUID.randomUUID().toString());
applicationWorkerNode.setSshUsername(applicationNodeDto.sshUsername());
applicationWorkerNode.setPublicIp(applicationNodeDto.publicIp());
applicationWorkerNode.setApplicationMasterNode(masterNode);
applicationWorkerNode.setDateCreated(new Date());
applicationWorkerNode.setWireguardPrivateKey(wireguardPrivateKey);
applicationWorkerNode.setWireguardPublicKey(wireguardPublicKey);
applicationWorkerNode.setWireguardIp(wireguardWorkerIp);
applicationWorkerNode.setOpenSSLPrivateKey(applicationNodeDto.privateKeyBase64());
applicationWorkerNode.setOpenSSLPublicKey(applicationNodeDto.publicKey());
applicationWorkerNodeRepository.persist(applicationWorkerNode);
logService.log(logList, Level.INFO, ONM, "SUCCESS -> Application Node Worker (" + applicationNodeDto.publicIp() +
"," + applicationNodeDto.applicationUUID() + ") successfully persisted to DB!");
} catch (Exception e) {
logService.log(logList, Level.WARNING, ONM, "FAILURE -> The Application Node Worker (" + applicationNodeDto.publicIp() +
"," + applicationNodeDto.applicationUUID() + ") failed to be persisted to DB!");
}
}
@Transactional
public List<LogDto> evaluateNodeCreation(ApplicationNodeDto applicationNodeDto) {
var logList = new ArrayList<LogDto>();
// Create WG Key Pair Function
var wireguardKeyPair = wgKeyPairGeneratorService.createWireguardKeyPair(applicationNodeDto.publicIp());
var wireguardPrivateKey = wireguardKeyPair.get("private");
var wireguardPublicKey = wireguardKeyPair.get("public");
logService.log(logList, Level.INFO, ONM, "Created WG Key Pair for Application Node with Public IP: " + applicationNodeDto.publicIp());
if (applicationNodeDto.isMaster().equals(Boolean.TRUE)) {
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-server-create.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "SCP FILE wg-server-create.sh to HOST: " + applicationNodeDto.publicIp());
remoteCodeExecutionService.scpFile(applicationNodeDto.sshUsername(),applicationNodeDto.publicIp(),
22,applicationNodeDto.privateKeyBase64(),30L,
wgBootstrapAgentScriptsDir + "/server/wg-server-create.sh",
"wireguard",null);
logService.log(logList, Level.INFO, ONM, "SCP COMPLETED! Ready to run wg-server-create.sh to HOST: " + applicationNodeDto.publicIp());
var permissionsCommand = "sudo chmod +x /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-server-create.sh";
var executeCommand = "sudo /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-server-create.sh " + wireguardPrivateKey + " " +
wireguardPublicKey + " " + " " + wireguardDefaultServerIp;
remoteCodeExecutionService.runCommand(applicationNodeDto.sshUsername(),applicationNodeDto.privateKeyBase64(),applicationNodeDto.publicIp(),
22,30L,
permissionsCommand + ";" + executeCommand, null);
logService.log(logList, Level.INFO, ONM, "COMMAND wg-server-create.sh for HOST " + applicationNodeDto.publicIp() + " COMPLETED!");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-server-create.sh ------------------------------------");
// Persist to DB
persistApplicationMasterNode(logList, applicationNodeDto, applicationNodeDto.privateKeyBase64(), applicationNodeDto.publicKey(),
wireguardPrivateKey, wireguardPublicKey);
} else {
String wireguardWorkerIp = wireguardNetworkPortion + "2";
ApplicationMasterNode masterNode = applicationMasterNodeRepository.findByApplicationUUID(applicationNodeDto.applicationUUID());
if (masterNode != null) {
List<ApplicationWorkerNode> workerNodes = applicationWorkerNodeRepository.findWorkerNodesByMasterNode(masterNode);
logService.log(logList, Level.INFO, ONM, "Worker Nodes " + workerNodes.size());
if (!workerNodes.isEmpty()) wireguardWorkerIp = wireguardNetworkPortion + (workerNodes.size() + 2);
var workerNodeClientName = "wg" + wireguardWorkerIp;
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-create_server.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "SCP FILE wg-client-create_server.sh to HOST: " + masterNode.getPublicIp());
remoteCodeExecutionService.scpFile(masterNode.getSshUsername(),masterNode.getPublicIp(),
22, masterNode.getOpenSSLPrivateKey(), 30L,
wgBootstrapAgentScriptsDir + "/client/wg-client-create_server.sh",
"wireguard",null);
logService.log(logList, Level.INFO, ONM, "SCP COMPLETED! Ready to run wg-client-create_server.sh to HOST: " + masterNode.getPublicIp());
var permissionsCommandServer = "sudo chmod +x /home/" + masterNode.getSshUsername() + "/wireguard/wg-client-create_server.sh";
var executeCommandServer = "sudo /home/" + masterNode.getSshUsername() + "/wireguard/wg-client-create_server.sh " + workerNodeClientName + " " + wireguardPrivateKey + " " +
wireguardPublicKey + " " + masterNode.getSshUsername() + " " + masterNode.getWireguardPublicKey() + " " + masterNode.getPublicIp()+":"+"51820" + " " +
wireguardWorkerIp + " " + wireguardAllowedIps;
remoteCodeExecutionService.runCommand(masterNode.getSshUsername(),masterNode.getOpenSSLPrivateKey(),masterNode.getPublicIp(),
22,30L,
permissionsCommandServer + ";" + executeCommandServer, null);
logService.log(logList, Level.INFO, ONM, "COMMAND wg-client-create_server.sh for HOST " + masterNode.getPublicIp() + " COMPLETED!");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-create_server.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-create_client.sh ------------------------------------");
remoteCodeExecutionService.scpFile(applicationNodeDto.sshUsername(),applicationNodeDto.publicIp(),
22,applicationNodeDto.privateKeyBase64(),30L,
wgBootstrapAgentScriptsDir + "/client/wg-client-create_client.sh",
"wireguard",null);
logService.log(logList, Level.INFO, ONM, "SCP COMPLETED! Ready to run wg-client-create_client.sh to HOST: " + applicationNodeDto.publicIp());
var permissionsCommandClient = "sudo chmod +x /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-client-create_client.sh";
var executeCommandClient = "sudo /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-client-create_client.sh " + applicationNodeDto.sshUsername() + " " +
"\"" + masterNode.getOpenSSLPrivateKey() + "\" " + masterNode.getPublicIp() + " " + workerNodeClientName + " " + masterNode.getSshUsername();
remoteCodeExecutionService.runCommand(applicationNodeDto.sshUsername(),applicationNodeDto.privateKeyBase64(),applicationNodeDto.publicIp(),
22,30L, permissionsCommandClient + ";" + executeCommandClient, null);
logService.log(logList, Level.INFO, ONM, "COMMAND wg-client-create_client.sh for HOST " + applicationNodeDto.publicIp() + " COMPLETED!");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-create_client.sh ------------------------------------");
// Persist to DB
persistApplicationWorkerNode(logList, applicationNodeDto, masterNode, wireguardPrivateKey, wireguardPublicKey, wireguardWorkerIp);
}
}
return logList;
}
@Transactional
public List<LogDto> evaluateNodeDeletion(ApplicationNodeDto applicationNodeDto) {
var logList = new ArrayList<LogDto>();
if(applicationNodeDto.isMaster().equals(Boolean.TRUE)) {
ApplicationMasterNode masterNode = applicationMasterNodeRepository.findByApplicationUUID(applicationNodeDto.applicationUUID());
if (masterNode == null) {
logService.log(logList, Level.INFO, ONM, "FAILURE -> Could not find an Application Master Node with applicationUUID " +
applicationNodeDto.applicationUUID());
return logList;
}
// Check If Master has workers below him
List<ApplicationWorkerNode> workerNodes = applicationWorkerNodeRepository.findWorkerNodesByMasterNode(masterNode);
if(workerNodes.isEmpty()) {
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-server-delete.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "SCP FILE wg-server-delete.sh to HOST: " + applicationNodeDto.publicIp());
remoteCodeExecutionService.scpFile(applicationNodeDto.sshUsername(),applicationNodeDto.publicIp(),
22,applicationNodeDto.privateKeyBase64(),30L,
wgBootstrapAgentScriptsDir + "/server/wg-server-delete.sh",
"wireguard",null);
logService.log(logList, Level.INFO, ONM, "SCP COMPLETED! Ready to run wg-server-delete.sh to HOST: " + applicationNodeDto.publicIp());
var permissionsCommand = "sudo chmod +x /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-server-delete.sh";
var executeCommand = "sudo /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-server-delete.sh " + applicationNodeDto.sshUsername();
remoteCodeExecutionService.runCommand(applicationNodeDto.sshUsername(),applicationNodeDto.privateKeyBase64(),applicationNodeDto.publicIp(),
22,30L,
permissionsCommand + ";" + executeCommand, null);
logService.log(logList, Level.INFO, ONM, "COMMAND wg-server-delete.sh for HOST " + applicationNodeDto.publicIp() + " COMPLETED!");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-server-delete.sh ------------------------------------");
deleteApplicationMasterNode(logList, masterNode);
} else {
logService.log(logList, Level.INFO, ONM, "The Application Master Node with PublicIP " + applicationNodeDto.publicIp() +
" and applicationUUID " + applicationNodeDto.applicationUUID() + " has " + workerNodes.size() + " worker nodes.");
//TODO: What happens when a request for deletion on a WG Server appears and it has workers running??
}
} else {
var workerNode = applicationWorkerNodeRepository.findWorkerByPublicIp(applicationNodeDto);
if(workerNode == null) {
logService.log(logList, Level.INFO, ONM, "FAILURE -> Could not find an Application Worker Node with applicationUUID " + applicationNodeDto.publicIp());
return logList;
}
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-delete_client.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "SCP FILE wg-client-delete_client.sh to HOST: " + applicationNodeDto.publicIp());
remoteCodeExecutionService.scpFile(applicationNodeDto.sshUsername(),applicationNodeDto.publicIp(),
22,applicationNodeDto.privateKeyBase64(),30L,
wgBootstrapAgentScriptsDir + "/client/wg-client-delete_client.sh",
"wireguard",null);
logService.log(logList, Level.INFO, ONM, "SCP COMPLETED! Ready to run wg-client-delete_client_script.sh to HOST: " + applicationNodeDto.publicIp());
var permissionsCommandClient = "sudo chmod +x /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-client-delete_client.sh";
var executeCommandClient = "sudo /home/" + applicationNodeDto.sshUsername() + "/wireguard/wg-client-delete_client.sh " + applicationNodeDto.sshUsername() +
" " + "wg" + workerNode.getWireguardIp();
remoteCodeExecutionService.runCommand(applicationNodeDto.sshUsername(),applicationNodeDto.privateKeyBase64(),applicationNodeDto.publicIp(),
22,30L,
permissionsCommandClient + ";" + executeCommandClient, null);
logService.log(logList, Level.INFO, ONM, "COMMAND wg-client-delete_client.sh for HOST " + applicationNodeDto.publicIp() + " COMPLETED!");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-delete_client.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-delete_server.sh ------------------------------------");
logService.log(logList, Level.INFO, ONM, "SCP FILE wg-client-delete_server.sh to HOST: " + workerNode.getApplicationMasterNode().getPublicIp());
remoteCodeExecutionService.scpFile(workerNode.getApplicationMasterNode().getSshUsername(),workerNode.getApplicationMasterNode().getPublicIp(),
22,workerNode.getApplicationMasterNode().getOpenSSLPrivateKey(),30L,
wgBootstrapAgentScriptsDir + "/client/wg-client-delete_server.sh",
"wireguard",null);
logService.log(logList, Level.INFO, ONM, "SCP COMPLETED! Ready to run wg-client-delete_server.sh to HOST: " + workerNode.getApplicationMasterNode().getPublicIp());
var permissionsCommandServer = "sudo chmod +x /home/" + workerNode.getApplicationMasterNode().getSshUsername() + "/wireguard/wg-client-delete_server.sh";
var executeCommandServer = "sudo /home/" + workerNode.getApplicationMasterNode().getSshUsername() + "/wireguard/wg-client-delete_server.sh " + "wg" + workerNode.getWireguardIp() +
" " + workerNode.getWireguardPublicKey() + " " + applicationNodeDto.sshUsername();
remoteCodeExecutionService.runCommand(workerNode.getApplicationMasterNode().getSshUsername(),workerNode.getApplicationMasterNode().getOpenSSLPrivateKey(),
workerNode.getApplicationMasterNode().getPublicIp(),22,30L, permissionsCommandServer + ";" + executeCommandServer, null);
logService.log(logList, Level.INFO, ONM, "COMMAND wg-client-delete_server.sh for HOST " + applicationNodeDto.publicIp() + " COMPLETED!");
logService.log(logList, Level.INFO, ONM, "------------------------------------ wg-client-delete_server.sh ------------------------------------");
deleteApplicationWorkerNode(logList, workerNode);
}
return logList;
}
private void deleteApplicationMasterNode(List<LogDto> logList, ApplicationMasterNode masterNode) {
try {
applicationMasterNodeRepository.delete(masterNode);
logService.log(logList, Level.INFO, ONM, "SUCCESS -> Application Node Master (" + masterNode.getPublicIp() + ", " +
masterNode.getApplicationUUID() + ") successfully deleted from the DB!");
} catch (Exception e) {
logService.log(logList, Level.WARNING, ONM, "FAILURE -> The Application Node Master (" + masterNode.getPublicIp() + ", " +
masterNode.getApplicationUUID() + ") failed to be deleted from the DB!");
}
}
private void deleteApplicationWorkerNode(List<LogDto> logList, ApplicationWorkerNode workerNode) {
try {
applicationWorkerNodeRepository.delete(workerNode);
logService.log(logList, Level.INFO, ONM, "SUCCESS -> Application Node Worker (" + workerNode.getPublicIp() + ", " +
workerNode.getApplicationMasterNode().getApplicationUUID() + ") successfully deleted from the DB!");
} catch (Exception e) {
logService.log(logList, Level.WARNING, ONM, "FAILURE -> The Application Node Worker (" + workerNode.getPublicIp() + ", " +
workerNode.getApplicationMasterNode().getApplicationUUID() + ") failed to be deleted from the DB!");
}
}
}

View File

@ -0,0 +1,24 @@
package eu.nebulous.service;
import eu.nebulous.dto.LogDto;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ApplicationScoped
public class LogService {
private static final Logger logger = Logger.getLogger(LogService.class.getName());
public void log(List<LogDto> logList, Level logLevel, String title, String message) {
var date = new Date();
// Add log events to logList
logList.add(new LogDto(date, logLevel, title, message));
// Log events
logger.log(logLevel, "{0}: {1}", new Object[]{date, message});
}
}

View File

@ -0,0 +1,135 @@
package eu.nebulous.service;
import jakarta.enterprise.context.ApplicationScoped;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.scp.client.ScpClientCreator;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@ApplicationScoped
public class RemoteCodeExecutionService {
private static final Logger logger = Logger.getLogger(RemoteCodeExecutionService.class.getName());
public void runCommand(String username, String privateKeyBase64, String host, int port,
long defaultTimeoutSeconds, String command, String password) {
File privateKeyFile = createTmpFile(privateKeyBase64);
var client = SshClient.setUpDefaultClient();
client.start();
try (var session = client.connect(username, host, port)
.verify(defaultTimeoutSeconds, TimeUnit.SECONDS).getSession()) {
if (password != null) {
session.addPasswordIdentity(password);
} else {
var fileKeyPairProvider = new FileKeyPairProvider();
fileKeyPairProvider.setPaths(Collections.singleton(Paths.get(privateKeyFile.getAbsolutePath())));
var key = fileKeyPairProvider.loadKeys(null).iterator().next();
session.addPublicKeyIdentity(key);
}
session.auth().verify(defaultTimeoutSeconds, TimeUnit.SECONDS); // Timeout
try (var responseStream = new ByteArrayOutputStream();
var channel = session.createExecChannel(command)) {
channel.setOut(responseStream);
try {
channel.open().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);
try (var pipedIn = channel.getInvertedIn()) {
pipedIn.write(command.getBytes());
pipedIn.flush();
}
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds));
var responseString = responseStream.toString();
logger.log(Level.INFO, "Response: {0}", new Object[]{responseString});
} finally {
channel.close(false);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
client.stop();
privateKeyFile.delete();
}
}
public void scpFile(String username, String host, int port, String privateKeyBase64, long defaultTimeoutSeconds,
String localFilePath, String remoteTargetFolder, String password) {
File privateKeyFile = createTmpFile(privateKeyBase64);
var client = SshClient.setUpDefaultClient();
client.start();
try (var session = client.connect(username, host, port)
.verify(defaultTimeoutSeconds, TimeUnit.SECONDS).getSession()) {
if (password != null) {
session.addPasswordIdentity(password);
} else {
var fileKeyPairProvider = new FileKeyPairProvider();
fileKeyPairProvider.setPaths(Collections.singleton(Paths.get(privateKeyFile.getAbsolutePath())));
var key = fileKeyPairProvider.loadKeys(null).iterator().next();
session.addPublicKeyIdentity(key);
}
session.auth().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);
var creator = ScpClientCreator.instance();
var scpClient = creator.createScpClient(session);
// To SCP a file to the remote system
scpClient.upload(localFilePath, "/home/" + username + "/" + remoteTargetFolder);
} catch (IOException e) {
e.printStackTrace();
} finally {
client.stop();
privateKeyFile.delete();
}
}
private File createTmpFile(String privateKey) {
try {
// Create temp file.
var temp = File.createTempFile("originPK" + UUID.randomUUID(), ".txt");
// Write to temp file
var out = new BufferedWriter(new FileWriter(temp));
var decodedString = new String(Base64.getMimeDecoder().decode(privateKey.getBytes()), StandardCharsets.UTF_8);
out.write(decodedString);
out.close();
return temp;
} catch (IOException e) {
logger.log(Level.SEVERE, "{0} -> Problem creating tmp file for Origin Private Key File", new Object[]{new Date()});
return null;
}
}
}

View File

@ -0,0 +1,82 @@
package eu.nebulous.service;
import jakarta.enterprise.context.ApplicationScoped;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.security.Key;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.Security;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ApplicationScoped
public class SSHKeyPairGeneratorService {
private static final Logger logger = Logger.getLogger(SSHKeyPairGeneratorService.class.getName());
public Map<String, String> createOpenSSL(String publicIp) {
var openSSLKeyPairHashMap = new HashMap<String, String>();
try {
Security.addProvider(new BouncyCastleProvider());
// Generate the RSA Key Pair
var keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
var pair = keyGen.generateKeyPair();
var privateKeyString = convertKeyToString(pair.getPrivate());
var privateKeyBase64String = Base64.getEncoder().encodeToString(privateKeyString.getBytes());
openSSLKeyPairHashMap.put("private", privateKeyBase64String);
// Output private key
logger.log(Level.INFO, "{0}: SUCCESS -> OpenSSL Private Key Base64 for {1} just created: {2}",
new Object[]{new Date(), publicIp, privateKeyBase64String});
// Convert public key to SSH format
var sshPublicKey = convertPublicKeyToSSHFormat(pair.getPublic());
openSSLKeyPairHashMap.put("public", sshPublicKey + " wg-public-key");
logger.log(Level.INFO, "{0}: SUCCESS -> OpenSSL Public Key (SSH Format) for {1} just created: {2} wg-public-key",
new Object[]{new Date(), publicIp, sshPublicKey});
} catch (Exception e) {
logger.log(Level.WARNING, "{0}: FAILURE -> Error generating OpenSSL Key Pair for {1}",
new Object[]{new Date(), publicIp});
}
return openSSLKeyPairHashMap;
}
private static String convertKeyToString(Key key) throws IOException {
var writer = new StringWriter();
try (var pemWriter = new JcaPEMWriter(writer)) {
pemWriter.writeObject(key);
}
return writer.toString();
}
private static String convertPublicKeyToSSHFormat(PublicKey publicKey) throws IOException {
var rsaPublicKey = (RSAPublicKey) publicKey;
var byteOs = new ByteArrayOutputStream();
var dos = new DataOutputStream(byteOs);
dos.writeInt("ssh-rsa".getBytes().length);
dos.write("ssh-rsa".getBytes());
dos.writeInt(rsaPublicKey.getPublicExponent().toByteArray().length);
dos.write(rsaPublicKey.getPublicExponent().toByteArray());
dos.writeInt(rsaPublicKey.getModulus().toByteArray().length);
dos.write(rsaPublicKey.getModulus().toByteArray());
var publicKeyEncoded = new String(Base64.getEncoder().encode(byteOs.toByteArray()));
return "ssh-rsa " + publicKeyEncoded;
}
}

View File

@ -0,0 +1,50 @@
package eu.nebulous.service;
import jakarta.enterprise.context.ApplicationScoped;
import org.bouncycastle.crypto.generators.X25519KeyPairGenerator;
import org.bouncycastle.crypto.params.X25519KeyGenerationParameters;
import org.bouncycastle.crypto.params.X25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.X25519PublicKeyParameters;
import org.bouncycastle.util.encoders.Base64;
import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ApplicationScoped
public class WGKeyPairGeneratorService {
private static final Logger logger = Logger.getLogger(WGKeyPairGeneratorService.class.getName());
public Map<String, String> createWireguardKeyPair(String publicIp) {
var wireguardKeyPairHashMap = new HashMap<String, String>();
// Initialize key generator
var keyPairGenerator = new X25519KeyPairGenerator();
keyPairGenerator.init(new X25519KeyGenerationParameters(new SecureRandom()));
// Generate key pair
var keyPair = keyPairGenerator.generateKeyPair();
// Extract private and public keys
var privateKey = (X25519PrivateKeyParameters) keyPair.getPrivate();
var publicKey = (X25519PublicKeyParameters) keyPair.getPublic();
// Encode keys to Base64
var privateKeyBase64 = Base64.toBase64String(privateKey.getEncoded());
var publicKeyBase64 = Base64.toBase64String(publicKey.getEncoded());
wireguardKeyPairHashMap.put("private", privateKeyBase64);
wireguardKeyPairHashMap.put("public", publicKeyBase64);
// Output the keys
logger.log(Level.INFO, "{0}: SUCCESS -> Private Key for {1} just created: {2}",
new Object[]{new Date(), publicIp, privateKeyBase64});
logger.log(Level.INFO, "{0}: SUCCESS -> Public Key for {1} just created: {2}",
new Object[]{new Date(), publicIp, publicKeyBase64});
return wireguardKeyPairHashMap;
}
}

View File

@ -0,0 +1,26 @@
package eu.nebulous.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.nebulous.exception.NotFoundAlertException;
import jakarta.enterprise.context.ApplicationScoped;
import java.io.PrintWriter;
import java.io.StringWriter;
@ApplicationScoped
public class Util {
public String exceptionResponse(Exception e){
var errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
return errors.toString();
}
public String toString(Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new NotFoundAlertException(e.toString());
}
}
}

View File

@ -0,0 +1,39 @@
mp:
openapi:
extensions:
smallrye:
info:
title: 'API Specification'
version: '1.0'
description: 'Exposed REST Services in order to talk with the world'
name: 'NebulOus Overlay Network Manager'
quarkus:
datasource:
db-kind: postgresql
jdbc:
url: ${POSTGRES_CONNECTION_STRING}
username: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
hibernate-orm:
database:
generation: update
smallrye-openapi:
path: '/api/openapi'
security-scheme: 'jwt'
security-scheme-name: 'Swagger Authentication'
security-scheme-description: 'User Authentication through Keycloak'
swagger-ui:
title: 'API Documentation'
theme: material
footer: &#169; 2024
always-include: true
path: '/api/swagger'
"%prod":
quarkus:
package:
type: uber-jar

View File

@ -0,0 +1,7 @@
# Create Client
* Server Name: wg0
* Client Name: $CLIENT_NAME
* Wireguard Client Directory: /etc/wireguard/clients/$CLIENT_NAME
* Client Conf: /etc/wireguard/clients/$CLIENT_NAME/$CLIENT_NAME.conf
* Server Conf: /etc/wireguard/wg0.conf

View File

@ -0,0 +1,40 @@
#!/bin/bash
# Check if sufficient arguments are provided
if [ "$#" -ne 5 ]; then
echo "Usage: $0 <WORKER_SSH_USERNAME> <OPENSSL_PRIVATE_KEY> <SERVER_IP> <CLIENT_NAME> <MASTER_SSH_USERNAME>"
exit 1
fi
# Script parameter
WORKER_SSH_USERNAME="$1"
OPENSSL_PRIVATE_KEY="$2"
SERVER_IP="$3"
CLIENT_NAME="$4"
MASTER_SSH_USERNAME="$5"
# Update Package Repository. Upgrade and Autoremove Packages
sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
sudo DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get -y autoremove
# Step 1: Install WireGuard
if ! command -v wg > /dev/null; then
sudo DEBIAN_FRONTEND=noninteractive apt install -y wireguard
sudo DEBIAN_FRONTEND=noninteractive apt install -y resolvconf
fi
# Step 2: Base64 Decode the OpenSSH Private Key file
echo $OPENSSL_PRIVATE_KEY | base64 -d --ignore-garbage > /home/$WORKER_SSH_USERNAME/wg-private-key.key
chmod 400 /home/$WORKER_SSH_USERNAME/wg-private-key.key
# Step 3: Secure Copy to WG Server to get your conf file
scp -o StrictHostKeyChecking=no -i /home/$WORKER_SSH_USERNAME/wg-private-key.key $MASTER_SSH_USERNAME@$SERVER_IP:/home/$MASTER_SSH_USERNAME/wireguard/clients/$CLIENT_NAME/$CLIENT_NAME.conf /home/$WORKER_SSH_USERNAME/wireguard
sudo cp /home/$WORKER_SSH_USERNAME/wireguard/$CLIENT_NAME.conf /etc/wireguard/$CLIENT_NAME.conf
# Step 4: Enable and Start WireGuard Client Interface
sudo systemctl enable wg-quick@$CLIENT_NAME
sudo systemctl start wg-quick@$CLIENT_NAME
echo "WireGuard client configured and started for $CLIENT_NAME"

View File

@ -0,0 +1,64 @@
#!/bin/bash
# Check if sufficient arguments are provided
if [ "$#" -ne 8 ]; then
echo "Usage: $0 <WG_CLIENT_NAME> <WG_Client_Private_Key> <WG_Client_Public_Key> <SSH_Username> <Server_PublicKey> <Server_IP:Port> <Client_VPN_IP> <AllowedIPs>"
exit 1
fi
# Script parameters
SERVER_NAME="wg0"
CLIENT_NAME="$1"
WG_CLIENT_PRIVATE_KEY="$2"
WG_CLIENT_PUBLIC_KEY="$3"
SSH_USERNAME="$4"
SERVER_PUBLIC_KEY="$5"
SERVER_IP_PORT="$6"
CLIENT_VPN_IP="$7"
ALLOWED_IPS="$8"
WG_DIR="/etc/wireguard/clients/$CLIENT_NAME"
CLIENT_CONF="$WG_DIR/${CLIENT_NAME}.conf"
SERVER_CONF="/etc/wireguard/${SERVER_NAME}.conf"
# Step 1: Install WireGuard (if not already installed)
if ! command -v wg > /dev/null; then
sudo DEBIAN_FRONTEND=noninteractive apt install -y wireguard
fi
# Step 2: Create client directory
sudo mkdir -p "$WG_DIR"
mkdir -p /home/$SSH_USERNAME/wireguard/clients/$CLIENT_NAME
# Step 3: Generate Client Keys
sudo echo $WG_CLIENT_PRIVATE_KEY > "$WG_DIR/${CLIENT_NAME}_privatekey"
sudo echo $WG_CLIENT_PUBLIC_KEY > "$WG_DIR/${CLIENT_NAME}_publickey"
client_private_key=$(sudo cat "$WG_DIR/${CLIENT_NAME}_privatekey")
client_public_key=$(sudo cat "$WG_DIR/${CLIENT_NAME}_publickey")
# Step 4: Configure WireGuard Client
sudo bash -c "cat > $CLIENT_CONF <<EOF
[Interface]
PrivateKey = $client_private_key
Address = $CLIENT_VPN_IP
DNS = 1.1.1.1 # Change this if you have a preferred DNS server
[Peer]
PublicKey = $SERVER_PUBLIC_KEY
Endpoint = $SERVER_IP_PORT
AllowedIPs = $ALLOWED_IPS
PersistentKeepalive = 25
EOF"
# Step 5: Update Server Configuration
sudo cp $CLIENT_CONF /home/$SSH_USERNAME/wireguard/clients/$CLIENT_NAME/$CLIENT_NAME.conf
sudo systemctl stop wg-quick@${SERVER_NAME}
sudo bash -c "echo -e '\n[Peer]\nPublicKey = $client_public_key\nAllowedIPs = $CLIENT_VPN_IP' >> $SERVER_CONF"
# Step 6: Restart WireGuard to apply changes
sudo systemctl restart wg-quick@${SERVER_NAME}
echo "Client configuration for $CLIENT_NAME created and added to server config."
echo "Transfer the client configuration to your client machine. Example command:"
echo "scp $CLIENT_CONF user@client-ip:/path/to/destination"

View File

@ -0,0 +1,35 @@
#!/bin/bash
# Check if sufficient arguments are provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <SSH_USERNAME> <WG_INTERFACE_NAME>"
exit 1
fi
# Script parameter
SSH_USERNAME="$1"
WG_INTERFACE_NAME="$2"
# Step 1: Stop and Disable WireGuard Interface
sudo systemctl stop wg-quick@$WG_INTERFACE_NAME
sudo systemctl disable wg-quick@$WG_INTERFACE_NAME
# Step 2: Remove Wireguard packages
sudo apt-get remove --purge -y wireguard
sudo apt-get autoremove -y
echo "Wireguard packages have been removed."
# Step 3: Remove Wireguard related directories
sudo rm -rf /etc/wireguard
sudo rm -rf /home/$SSH_USERNAME/wireguard
echo "WireGuard configuration files removed."
# Step 4: Remove WG OpenSSL Private Key
sudo rm -rf /home/$SSH_USERNAME/wg-private-key.key
# Step 5: Remove OpenSSL Public Key
sed -i '/wireguard-pub/d' /home/$SSH_USERNAME/.ssh/authorized_keys
echo "WireGuard client $WG_INTERFACE_NAME has been stopped and disabled."

View File

@ -0,0 +1,25 @@
#!/bin/bash
# Check if the client public key is provided
if [ "$#" -ne 3 ]; then
echo "Usage: $0 <Client_Name> <Client_PublicKey> <SSH_Username>"
exit 1
fi
# Script parameter
SERVER_NAME="wg0"
CLIENT_NAME="$1"
CLIENT_PUBLIC_KEY="$2"
SSH_USERNAME="$3"
# Step 1: Remove the client configuration from the server
sudo wg set ${SERVER_NAME} peer ${CLIENT_PUBLIC_KEY} remove
# Step 2: Remove the client config file
sudo rm -rf /etc/wireguard/clients/${CLIENT_NAME}
sudo rm -rf /home/$SSH_USERNAME/wireguard/clients/${CLIENT_NAME}
# Step 3: Restart WireGuard to apply changes
sudo systemctl restart wg-quick@${SERVER_NAME}
echo "Client with public key $CLIENT_PUBLIC_KEY has been removed from the server configuration."

View File

@ -0,0 +1,60 @@
#!/bin/bash
# "CREATE" or "DELETE" Overlay Node
ACTION=$1
# Define Application Node Type ("MASTER","WORKER")
NODE_TYPE=$2
# Application UUID
APPLICATION_UUID=$3
# Overlay Network Manager Public IP
ONM_IP=$4
# Get the public IP
public_ip=$(curl -s http://httpbin.org/ip | grep -oP '(?<="origin": ")[^"]*')
# Get the Application UUID from the environment variable
application_uuid=$APPLICATION_UUID
# Get the currently logged in user (assuming single user login)
logged_in_user=$(whoami)
# Get the isMaster variable from the environment variable
if [ "$NODE_TYPE" == "MASTER" ]; then
IS_MASTER="true";
elif [ "$NODE_TYPE" == "WORKER" ]; then
IS_MASTER="false"
fi
# Check if string1 is equal to string2
if [ "$ACTION" == "CREATE" ]; then
echo "Creating OpenSSH Public/Private Key Pair..."
# Create Wireguard Folder to accept the wireguard scripts
mkdir -p /home/${logged_in_user}/wireguard
# Create OpenSSH Public/Private Key files
ssh-keygen -C wireguard-pub -t rsa -b 4096 -f /home/${logged_in_user}/wireguard/wireguard -N ""
cat /home/${logged_in_user}/wireguard/wireguard.pub >> /home/${logged_in_user}/.ssh/authorized_keys
fi
PRIVATE_KEY_FILE=$(cat /home/${logged_in_user}/wireguard/wireguard | base64 | tr '\n' ' ')
PAYLOAD=$(cat <<EOF
{
"privateKeyBase64": "${PRIVATE_KEY_FILE}",
"publicKey": "$(</home/${logged_in_user}/wireguard/wireguard.pub)",
"publicIp": "${public_ip}",
"applicationUUID": "${application_uuid}",
"sshUsername": "${logged_in_user}",
"isMaster": "$IS_MASTER"
}
EOF
)
echo "$PAYLOAD"
if [ "$ACTION" == "CREATE" ]; then
curl -v -X POST -H "Content-Type: application/json" -d "$PAYLOAD" http://${ONM_IP}:8082/api/v1/node/create
elif [ "$ACTION" == "DELETE" ]; then
curl -v -X DELETE -H "Content-Type: application/json" -d "$PAYLOAD" http://${ONM_IP}:8082/api/v1/node/delete
fi

View File

@ -0,0 +1,7 @@
# Create WG Server
* Interface Name: wg0
* Listen Port: 51820
* WG Server IP: 192.168.55.1
* WG Server Keys Directory: /etc/wireguard/server_keys
* WG Server Conf file: /etc/wireguard/wg0.conf

View File

@ -0,0 +1,54 @@
#!/bin/bash
# Check if sufficient arguments are provided
if [ "$#" -ne 3 ]; then
echo "Usage: $0 <WG_Server_Private_Key> <WG_Server_Public_Key> <WG_Server_IP>"
exit 1
fi
# Script parameters
WG_SERVER_PRIVATE_KEY="$1"
WG_SERVER_PUBLIC_KEY="$2"
WG_INTERFACE="wg0"
SERVER_IP="$3"
LISTEN_PORT="51820"
WG_DIR="/etc/wireguard"
SERVER_KEYS_DIR="$WG_DIR/server_keys"
SERVER_CONF="$WG_DIR/$WG_INTERFACE.conf"
# Update Package Repository. Upgrade and Autoremove Packages
sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
sudo DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get -y autoremove
# Step 1: Install WireGuard package
if ! command -v wg > /dev/null; then
sudo DEBIAN_FRONTEND=noninteractive apt install -y wireguard
sudo DEBIAN_FRONTEND=noninteractive apt install -y resolvconf
fi
# Step 2: Create directories for keys and configuration
sudo mkdir -p "$SERVER_KEYS_DIR"
sudo mkdir -p "$WG_DIR"
# Step 3: Generate Server Keys
sudo echo $WG_SERVER_PRIVATE_KEY > "$SERVER_KEYS_DIR/${WG_INTERFACE}_privatekey"
sudo echo $WG_SERVER_PUBLIC_KEY > "$SERVER_KEYS_DIR/${WG_INTERFACE}_publickey"
server_private_key=$(sudo cat "$SERVER_KEYS_DIR/${WG_INTERFACE}_privatekey")
# Step 4: Create Server Configuration File
sudo bash -c "cat > $SERVER_CONF <<EOF
[Interface]
Address = $SERVER_IP
ListenPort = $LISTEN_PORT
PrivateKey = $server_private_key
SaveConfig = true
EOF"
# Step 5: Enable and Start WireGuard
sudo systemctl enable wg-quick@$WG_INTERFACE
sudo systemctl start wg-quick@$WG_INTERFACE
echo "WireGuard server is up and running!"
echo "Server configuration is located at $SERVER_CONF"
echo "Server keys are stored in $SERVER_KEYS_DIR"

View File

@ -0,0 +1,28 @@
#!/bin/bash
# Script parameter: WireGuard interface name (e.g., wg0)
WG_INTERFACE=wg0
# Script parameter
SSH_USERNAME="$1"
# Step 1: Disable and stop the WireGuard service
sudo systemctl stop wg-quick@$WG_INTERFACE
sudo systemctl disable wg-quick@$WG_INTERFACE
# Step 2: Remove the WireGuard interface
sudo ip link delete $WG_INTERFACE
# Step 3: Remove Wiregaurd packages
sudo apt remove --purge -y wireguard
sudo apt autoremove -y
# Step 4: Remove OpenSSL Public Key
sed -i '/wireguard-pub/d' /home/$SSH_USERNAME/.ssh/authorized_keys
# Step 5: Remove Wireguard related directories
sudo rm -rf /etc/wireguard
sudo rm -rf /home/$SSH_USERNAME/wireguard
echo "WireGuard has been uninstalled."
echo "WireGuard server $WG_INTERFACE has been removed."

View File

@ -8,15 +8,15 @@
- nebulous-overlay-network-manager-container-images
description: Build the container images.
files: &image_files
- ^java-spring-boot-demo/
- ^network-manager/
vars: &image_vars
promote_container_image_job: nebulous-overlay-network-manager-upload-container-images
container_images:
- context: java-spring-boot-demo
- context: network-manager
registry: quay.io
repository: quay.io/nebulous/overlay-network-manager-java-spring-boot-demo
repository: quay.io/nebulous/overlay-network-manager
namespace: nebulous
repo_shortname: overlay-network-manager-java-spring-boot-demo
repo_shortname: overlay-network-manager
repo_description: ""
- job:
@ -44,7 +44,7 @@
description: Run Hadolint on Dockerfile(s).
vars:
dockerfiles:
- java-spring-boot-demo/Dockerfile
- network-manager/Dockerfile
- job:
name: nebulous-overlay-network-manager-helm-lint