Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bb01cf2
ignore vagrant files
hitnik Nov 24, 2025
0823b47
protocol compliant
hitnik Nov 24, 2025
27dedb7
change device mac address
hitnik Nov 25, 2025
f8192a5
connection module
hitnik Nov 25, 2025
62172ef
ntp module comliant
hitnik Nov 26, 2025
d373200
changes in readme
hitnik Nov 26, 2025
7eb954f
dns module
hitnik Nov 27, 2025
01a2dec
tls outbound complient
hitnik Nov 28, 2025
b7c4f11
tls compliant server
hitnik Nov 30, 2025
5418bed
firewall
hitnik Nov 30, 2025
abd8401
intermidiate certificate
hitnik Dec 2, 2025
e393b78
Merge branch 'dev' into vm-device
hitnik Dec 2, 2025
8ac8ddc
pylint
hitnik Dec 2, 2025
059783b
add ansible
hitnik Dec 5, 2025
5d5c0d0
modbus non-compliant
hitnik Dec 7, 2025
0ed92d4
fix modbus error
hitnik Dec 8, 2025
cb14d01
ftp ssh non-compiant
hitnik Dec 8, 2025
0d56b8c
smtp imamp pop
hitnik Dec 9, 2025
c76589b
http 80 port
hitnik Dec 9, 2025
e4dc3d0
snmp server
hitnik Dec 9, 2025
38787be
vnc
hitnik Dec 9, 2025
fcd7787
tftp
hitnik Dec 9, 2025
d61682d
tftp ntp
hitnik Dec 9, 2025
2c67b15
bacnet
hitnik Dec 9, 2025
814a8a6
dhcp server
hitnik Dec 10, 2025
711475a
readme improve
hitnik Dec 11, 2025
f5d1a60
dhcp server non-compliant
hitnik Dec 12, 2025
8020461
non-comliant mac manufacturer
hitnik Dec 13, 2025
0a8fd3e
non-compliant connection module
hitnik Dec 15, 2025
805667d
ntp non-compliant
hitnik Dec 15, 2025
2645bfb
tls non-compliant
hitnik Dec 17, 2025
0a69722
feature not detected config
hitnik Dec 18, 2025
4a58e8b
refactor compliant config
hitnik Dec 19, 2025
3f1f968
Merge branch 'dev' into vm-device
hitnik Dec 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,14 @@ testing/unit/services/output/
make/DEBIAN/postinst

testrun.log

# Ignore vagrant files
test_vm/.vagrant/

# Ingnore TLS test certificates
test_vm/certs/
test_vm/*.cnf
test_vm/*.csr
test_vm/*.pem
test_vm/*.key
test_vm/*.crt
60 changes: 55 additions & 5 deletions test_vm/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ This guide will help you set up a Vagrant VM with two network interfaces:

## 1. Install Required Packages and Dependencies



```bash
sudo wget -O- https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo add-apt-repository -y "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update
sudo apt-get install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager \
ruby ruby-dev libvirt-dev zlib1g-dev ebtables dnsmasq-base vagrant
sudo apt-get install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils \
ruby ruby-dev libvirt-dev zlib1g-dev ebtables dnsmasq-base vagrant ansible

```

Expand Down Expand Up @@ -47,7 +51,13 @@ sudo ip link delete enbr99 type bridge

## 6. Create an Isolated libvirt Network Without IP and DHCP

### Create the file /tmp/hostonly-noip.xml:
### Create the file /tmp/hostonly-noip.xml

```bash
nano /tmp/hostonly-noip.xml
```

file content

```xml
<network>
Expand All @@ -60,6 +70,8 @@ sudo ip link delete enbr99 type bridge
### Create and start the network:

```bash
sudo virsh net-destroy hostonly-noip || true
sudo virsh net-undefine hostonly-noip || true
sudo virsh net-define /tmp/hostonly-noip.xml
sudo virsh net-start hostonly-noip
sudo virsh net-autostart hostonly-noip
Expand All @@ -76,8 +88,46 @@ You should see hostonly-noip with status active.

## 8. Start the Virtual Machine

COMPLIANT DEVICE

```bash
./mock_ethtool.sh
hash -r
DEVICE=COMPLIANT vagrant up --provider=libvirt
DEVICE=COMPLIANT vagrant provision
./create_certificate.sh <VM IP>
```


NON-COMPLIANT DEVICE (WITHOUT TLS)

```bash
./restore_ethtool.sh
hash -r
DEVICE=NON-COMPLIANT vagrant up --provider=libvirt
DEVICE=NON-COMPLIANT vagrant provision
```

NON-COMPLIANT DEVICE (TLS ONLY)

```bash
vagrant up --provider=libvirt
./restore_ethtool.sh
hash -r
DEVICE=NON-COMPLIANT-TLS vagrant up --provider=libvirt
DEVICE=NON-COMPLIANT-TLS vagrant provision
```
If you see "Permission denied to /var/run/libvirt/libvirt-sock", check your libvirt group membership and restart your session.

NOT-DETECTED DEVICE

```bash
./mock_ethtool.sh
hash -r
DEVICE=NOT-DETECTED vagrant up --provider=libvirt
DEVICE=NOT-DETECTED vagrant provision
```

If you see "Permission denied to /var/run/libvirt/libvirt-sock", check your libvirt group membership and restart your session.


## 9. Start Testrun

47 changes: 42 additions & 5 deletions test_vm/Vagrantfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,55 @@
Vagrant.configure("2") do |config|
config.vm.box = "bento/ubuntu-24.04"
config.vm.box = "cloud-image/ubuntu-24.04"
config.vm.box_version = "20251126.0.0"
config.vm.hostname = "ubuntu-vm"
config.vm.network "private_network",
if ENV['DEVICE'] == 'COMPLIANT'
config.vm.network "private_network",
libvirt__network_name: "hostonly-noip",
auto_config: false,
mac: "52:54:00:12:34:56"
mac: "f0:d4:e2:f2:f5:41"
end
if ENV['DEVICE'] == 'NON-COMPLIANT-TLS'
config.vm.network "private_network",
libvirt__network_name: "hostonly-noip",
auto_config: false,
mac: "f0:d4:e2:f2:f5:42"
end
if ENV['DEVICE'] == 'NON-COMPLIANT'
config.vm.network "private_network",
libvirt__network_name: "hostonly-noip",
auto_config: false,
mac: "54:53:52:51:50:49"
end
if ENV['DEVICE'] == 'NOT-DETECTED'
config.vm.network "private_network",
libvirt__network_name: "hostonly-noip",
auto_config: false,
mac: "f0:d4:e2:f2:f5:43"
end

config.vm.provider :libvirt do |libvirt|
libvirt.memory = 2048
libvirt.cpus = 2
libvirt.graphics_type = "none"
end
if ENV['USE_ANSIBLE'] == '1'
if ENV['DEVICE'] == 'COMPLIANT'
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provision-compliant.yml"
end
end
if ENV['DEVICE'] == 'NON-COMPLIANT'
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provision-non-compliant.yml"
end
end
if ENV['DEVICE'] == 'NON-COMPLIANT-TLS'
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provision-non-compliant-tls.yml"
end
end
if ENV['DEVICE'] == 'NOT-DETECTED'
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provision.yml"
ansible.playbook = "provision-not-detected.yml"
end
end
end
135 changes: 135 additions & 0 deletions test_vm/create_cert_chain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/bin/bash
set -e

if [ -z "$1" ]; then
echo "Usage: $0 <VM_IP>"
exit 1
fi

VM_USER=vagrant
VM_PASS=vagrant
VM_IP="$1"
SSHPASS="sshpass -p $VM_PASS"

BASE_DIR="$(pwd)"
WORKDIR="$BASE_DIR/multi_ca_demo"
CERTS_DIR="$BASE_DIR/certs"
NGINX_CN="$VM_IP"

mkdir -p "$WORKDIR"
mkdir -p "$CERTS_DIR"
cd "$WORKDIR"

# Create CA extension config for intermediates
cat > ca_ext.cnf <<EOF
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = critical,CA:true,pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOF

# 1. Root CA
openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem -subj "/C=RU/O=MyOrgRoot/CN=MyRootCA"

# 2. Intermediate CA 1
openssl genrsa -out int1CA.key 4096
openssl req -new -key int1CA.key -out int1CA.csr -subj "/C=RU/O=MyOrgInt1/CN=MyInt1CA"
openssl x509 -req -in int1CA.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial \
-out int1CA.pem -days 1825 -sha256 -extfile ca_ext.cnf -extensions v3_ca

# 3. Intermediate CA 2
openssl genrsa -out int2CA.key 4096
openssl req -new -key int2CA.key -out int2CA.csr -subj "/C=RU/O=MyOrgInt2/CN=MyInt2CA"
openssl x509 -req -in int2CA.csr -CA int1CA.pem -CAkey int1CA.key -CAcreateserial \
-out int2CA.pem -days 1825 -sha256 -extfile ca_ext.cnf -extensions v3_ca

# 4. nginx server key and CSR
cat > openssl_nginx.cnf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = RU
O = MyOrganization
CN = $NGINX_CN

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
IP.1 = $NGINX_CN
EOF

openssl req -new -nodes -out nginx.csr -newkey rsa:2048 -keyout nginx.key -config openssl_nginx.cnf

# 5. nginx server cert signed by Intermediate CA 2
openssl x509 -req -in nginx.csr -CA int2CA.pem -CAkey int2CA.key -CAcreateserial \
-out nginx.crt -days 365 -sha256 -extfile openssl_nginx.cnf -extensions req_ext

# 6. Build full chain for nginx
cat nginx.crt int2CA.pem int1CA.pem rootCA.pem > nginx_fullchain.pem

echo "All certificates generated."

# 7. Copy certs and key to VM
$SSHPASS scp -o StrictHostKeyChecking=no nginx.key ${VM_USER}@${VM_IP}:/home/vagrant/nginx.key
$SSHPASS scp -o StrictHostKeyChecking=no nginx_fullchain.pem ${VM_USER}@${VM_IP}:/home/vagrant/nginx_fullchain.pem
$SSHPASS scp -o StrictHostKeyChecking=no int2CA.pem ${VM_USER}@${VM_IP}:/home/vagrant/int2CA.pem
$SSHPASS scp -o StrictHostKeyChecking=no int1CA.pem ${VM_USER}@${VM_IP}:/home/vagrant/int1CA.pem
$SSHPASS scp -o StrictHostKeyChecking=no rootCA.pem ${VM_USER}@${VM_IP}:/home/vagrant/rootCA.pem

# 8. Move certs to correct locations and configure nginx on VM
$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo mv /home/vagrant/nginx.key /etc/ssl/private/nginx.key"
$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo mv /home/vagrant/nginx_fullchain.pem /etc/ssl/certs/nginx_fullchain.pem"
$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo mv /home/vagrant/int2CA.pem /etc/ssl/certs/int2CA.pem"
$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo mv /home/vagrant/int1CA.pem /etc/ssl/certs/int1CA.pem"
$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo mv /home/vagrant/rootCA.pem /etc/ssl/certs/rootCA.pem"

$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo bash -c 'cat > /etc/nginx/sites-available/default <<EOF
server {
listen 443 ssl;
server_name $NGINX_CN;

ssl_certificate /etc/ssl/certs/nginx_fullchain.pem;
ssl_certificate_key /etc/ssl/private/nginx.key;

location / {
root /var/www/html;
index index.html index.htm;
}
}
EOF
'"

$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo nginx -t"
$SSHPASS ssh -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP} "sudo systemctl restart nginx"

echo "nginx configured with multi-level CA chain on $VM_IP"

# 9. Copy nginx_fullchain.pem, int2CA.pem, int1CA.pem, rootCA.pem from VM to certs subdirectory in working directory
$SSHPASS scp -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP}:/etc/ssl/certs/nginx_fullchain.pem "$CERTS_DIR/nginx_fullchain.pem"
$SSHPASS scp -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP}:/etc/ssl/certs/int2CA.pem "$CERTS_DIR/int2CA.pem"
$SSHPASS scp -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP}:/etc/ssl/certs/int1CA.pem "$CERTS_DIR/int1CA.pem"
$SSHPASS scp -o StrictHostKeyChecking=no ${VM_USER}@${VM_IP}:/etc/ssl/certs/rootCA.pem "$CERTS_DIR/rootCA.pem"
echo "Certificates copied from VM to $CERTS_DIR/"

# 10. Add rootCA.pem to trusted store on the client (Ubuntu/Debian)
if [ -f "$CERTS_DIR/rootCA.pem" ]; then
echo "Adding rootCA.pem to trusted store..."
sudo cp "$CERTS_DIR/rootCA.pem" /usr/local/share/ca-certificates/myorg-root-ca.crt
sudo update-ca-certificates
echo "rootCA.pem added to trusted store."
else
echo "rootCA.pem not found in $CERTS_DIR, skipping trusted store update."
fi

# 11. Remove temporary working directory
cd "$BASE_DIR"
rm -rf "$WORKDIR"
echo "Temporary directory $WORKDIR removed."
Loading
Loading