opiproject / sztp

Secure Zero Touch Provisioning (sZTP) in OPI
Apache License 2.0
20 stars 14 forks source link

feat: fetch dhcp leases from network-manager via dbus #427

Open bhoopesh369 opened 3 months ago

bhoopesh369 commented 3 months ago

I am not sure how to test this out since, currently, we have the lease file not managed by the network manager so the agent-6 errors out that sztp_url don't exist, I need to make the DHCP client connect to the DHCP server via network manager I'm not sure how to do this.

Thoughts?

closes https://github.com/opiproject/sztp/issues/418

glimchb commented 3 months ago

Please update https://github.com/opiproject/sztp/blob/main/scripts/run_agent.sh

bhoopesh369 commented 2 months ago

so the bootstrapURL in agent will now be a array of strings right?

type Agent struct {
    BootstrapURL  []string
        ...
}
glimchb commented 2 months ago

so the bootstrapURL in agent will now be a array of strings right?

type Agent struct {
  BootstrapURL  []string
        ...
}

yep, and then run/daemon will loop of this array

glimchb commented 2 months ago

I ran this and this is what I get

root@bf2:~/sztp# docker run --rm -it --privileged --network=host --mount type=bind,source=/var/run/dbus,target=/var/run/dbus,readonly  --mount type=bind,source=/mnt,target=/mnt --mount type=bind,source=/etc/ssh,target=/etc/ssh,readonly  --mount type=bind,source=/etc/os-release,target=/etc/os-release dbus /opi-sztp-agent daemon --bootstrap-trust-anchor-cert /mnt/opi.pem --device-end-entity-cert /mnt/nvidia_my_cert.pem --device-private-key /mnt/nvidia_private_key.pem --serial-number nvidia-serial-number
both '--bootstrap-url' and '--dhcp-lease-file' were not provided, trying to get the bootstrap URL via NetworkManager
2024/07/03 19:10:21 [INFO] Using user provides serial number: nvidia-serial-number
2024/07/03 19:10:21 lmao
2024/07/03 19:10:21 [INFO] Get the Bootstrap URL from DHCP client
2024/07/03 19:10:21 [Error] File  does not exist
2024/07/03 19:10:21 [INFO] Trying to get the URL from NetworkManager
2024/07/03 19:10:21 [INFO] sztp_redirect_url found:  []
2024/07/03 19:10:21 [INFO] failed to get Options property in DHCP4Config  / :  Object does not exist at path “/”
2024/07/03 19:10:21 [INFO] failed to get Options property in DHCP4Config  / :  Object does not exist at path “/”
2024/07/03 19:10:21 [ERROR]  sztp_redirect_urls not found in any active connection
2024/07/03 19:10:21 [ERROR]  sztp_redirect_urls not found in any active connection
2024/07/03 19:10:21 [INFO] Retrying in 5 seconds
  1. as I said before this log is confusing, because of the logic to try leases files first, I think is wrong

    2024/07/03 19:10:21 [INFO] Get the Bootstrap URL from DHCP client
    2024/07/03 19:10:21 [Error] File  does not exist

    especially that previous line says:

    both '--bootstrap-url' and '--dhcp-lease-file' were not provided, trying to get the bootstrap URL via NetworkManager
  2. not working

    2024/07/03 19:10:21 [INFO] failed to get Options property in DHCP4Config  / :  Object does not exist at path “/”

while this dbus.go example works:

package main

import (
    "fmt"
    "github.com/godbus/dbus/v5"
)

func main() {
    // Connect to the system bus
    conn, err := dbus.SystemBus()
    if err != nil {
        panic(fmt.Errorf("failed to connect to system bus: %v", err))
    }

    // Get NetworkManager object
    nm := conn.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")

    // Get PrimaryConnection property from NetworkManager object
    var primaryConnPath dbus.ObjectPath
    err = nm.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager", "PrimaryConnection").Store(&primaryConnPath)
    if err != nil {
        panic(fmt.Errorf("failed to get PrimaryConnection property: %v", err))
    }

    // Get Active Connection object
    connActive := conn.Object("org.freedesktop.NetworkManager", primaryConnPath)

    // Get Dhcp4Config property from Active Connection object
    var dhcpPath dbus.ObjectPath
    err = connActive.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager.Connection.Active", "Dhcp4Config").Store(&dhcpPath)
    if err != nil {
        panic(fmt.Errorf("failed to get Dhcp4Config property: %v", err))
    }

    // Get Options property from DHCP4Config object
    dhcp := conn.Object("org.freedesktop.NetworkManager", dhcpPath)
    var options map[string]dbus.Variant
    err = dhcp.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager.DHCP4Config", "Options").Store(&options)
    if err != nil {
        panic(fmt.Errorf("failed to get Options property: %v", err))
    }

    // Print sztp_redirect_urls option
    sztpRedirectURLs := options["sztp_redirect_urls"].Value().(string)
    fmt.Println(sztpRedirectURLs)
}

log from real hardware:

$ cd sztp-agent
$ docker run  --rm -it -v `pwd`:/app -w /app golang:alpine go get github.com/godbus/dbus/v5
$ docker run  --rm -it --privileged -v `pwd`:/app -v /var/run/dbus:/var/run/dbus -w /app golang:alpine go run dbus.go
go: downloading github.com/godbus/dbus/v5 v5.1.0
https://bootstrap:8080/restconf/operations/ietf-sztp-bootstrap-server:get-bootstrapping-data
codecov[bot] commented 2 months ago

Codecov Report

Attention: Patch coverage is 37.64706% with 106 lines in your changes missing coverage. Please review.

Project coverage is 61.93%. Comparing base (42fa12e) to head (69d5484). Report is 3 commits behind head on main.

Files Patch % Lines
sztp-agent/pkg/dhcp/network_manager.go 0.00% 45 Missing :warning:
sztp-agent/pkg/secureagent/daemon.go 28.57% 45 Missing :warning:
sztp-agent/pkg/dhcp/utils.go 65.85% 10 Missing and 4 partials :warning:
sztp-agent/cmd/daemon.go 0.00% 1 Missing :warning:
sztp-agent/cmd/run.go 0.00% 1 Missing :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #427 +/- ## ========================================== - Coverage 66.92% 61.93% -4.99% ========================================== Files 17 20 +3 Lines 780 867 +87 ========================================== + Hits 522 537 +15 - Misses 227 295 +68 - Partials 31 35 +4 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

bhoopesh369 commented 2 months ago

But yea I'm not able to get the bootstrap url via the network manager dbus

@glimchb do you have any idea, am I doing anything wrong?

glimchb commented 2 months ago

But yea I'm not able to get the bootstrap url via the network manager dbus

@glimchb do you have any idea, am I doing anything wrong?

if you take this code dbus.go:

package main

import (
    "fmt"
    "github.com/godbus/dbus/v5"
)

func main() {
    // Connect to the system bus
    conn, err := dbus.SystemBus()
    if err != nil {
        panic(fmt.Errorf("failed to connect to system bus: %v", err))
    }

    // Get NetworkManager object
    nm := conn.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")

    // Get PrimaryConnection property from NetworkManager object
    var primaryConnPath dbus.ObjectPath
    err = nm.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager", "PrimaryConnection").Store(&primaryConnPath)
    if err != nil {
        panic(fmt.Errorf("failed to get PrimaryConnection property: %v", err))
    }

    // Get Active Connection object
    connActive := conn.Object("org.freedesktop.NetworkManager", primaryConnPath)

    // Get Dhcp4Config property from Active Connection object
    var dhcpPath dbus.ObjectPath
    err = connActive.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager.Connection.Active", "Dhcp4Config").Store(&dhcpPath)
    if err != nil {
        panic(fmt.Errorf("failed to get Dhcp4Config property: %v", err))
    }

    // Get Options property from DHCP4Config object
    dhcp := conn.Object("org.freedesktop.NetworkManager", dhcpPath)
    var options map[string]dbus.Variant
    err = dhcp.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager.DHCP4Config", "Options").Store(&options)
    if err != nil {
        panic(fmt.Errorf("failed to get Options property: %v", err))
    }

    // Print sztp_redirect_urls option
    sztpRedirectURLs := options["sztp_redirect_urls"].Value().(string)
    fmt.Println(sztpRedirectURLs)
}

and run it like this:

$ cd sztp-agent
$ docker run  --rm -it -v `pwd`:/app -w /app golang:alpine go get github.com/godbus/dbus/v5
$ docker run  --rm -it --privileged -v `pwd`:/app -v /var/run/dbus:/var/run/dbus -w /app golang:alpine go run dbus.go
go: downloading github.com/godbus/dbus/v5 v5.1.0
https://bootstrap:8080/restconf/operations/ietf-sztp-bootstrap-server:get-bootstrapping-data

it works...

so I suggest to start like this with this simple approach... and then the difference is loop over all active connections... vs single connection... try to see if you can start with working example and add tiny bits and see when it breaks..

don;t work with sztp code base, just create a small standalone dbus.go file and run it individually...

glimchb commented 2 months ago

@bhoopesh369 can we split into 2 PRs?

it will be easier for me to review and merge first PR asap... and then we can work on second one together...

glimchb commented 2 months ago

@bhoopesh369 please check #438 . I added proper logic imho to the discovery function. I think the confusion before was due to mis-use of user given URL vs internal state of the agent... Now I added one more string to be separate USER given URL If missing - use DHCP discovery method...

bhoopesh369 commented 2 months ago

I think when the client container starts, it runs dhclient -d -v, which sends DHCP discover messages over the opi network which is managed by docker.

I think the connection is not managed by the network manager but rather by Docker’s internal networking.

Am I wrong here ? Wdyt @glimchb

bhoopesh369 commented 2 months ago

@bhoopesh369 can we split into 2 PRs?

  • one is just refactoring of getBootstrapURLsViaLeaseFile() function into dhcp folder ?
  • second is adding dbus ?

it will be easier for me to review and merge first PR asap... and then we can work on second one together...

Yea works ig

glimchb commented 2 months ago

Am I wrong here ? Wdyt @glimchb

you are talking about CI I'm talking about real hardware I tested this on... unrelated to CI and docker network - we will fix it separately

bhoopesh369 commented 2 months ago

Yep, I get that

But like I have my environment set up in docker. Is there like a readme file for me to set this up in local?

glimchb commented 2 months ago

Yep, I get that

But like I have my environment set up in docker. Is there like a readme file for me to set this up in local?

sure, https://github.com/opiproject/sztp/blob/main/scripts/run_agent.sh

glimchb commented 1 month ago

I opened https://github.com/opiproject/sztp/issues/441 to handle first and then we can rebase this PR on top Fixed #442

bhoopesh369 commented 1 month ago

@glimchb I tried setting up the DHCP server and client in local in the host network but nmcli doesnt show the options eventhough i have set the DHCP config file properly is there any script or something to run them in local?

The docker run commands I ran were:

docker run -d \
  --name dhcp \
  --env NODE_IP_SUBNET=10.1.58.0 \
  --env NODE_IP_NETMASK=255.255.254.0 \
  --env NODE_IP_RANGE_MIN=10.1.58.100 \
  --env NODE_IP_RANGE_MAX=10.1.59.200 \
  --env NODE_IP_ADDRESS=10.1.58.25 \
  --volume $(pwd)/dhcp:/opt \
  --cap-add=NET_BIND_SERVICE \
  --cap-add=NET_RAW \
  --network host \
  --entrypoint sh \
  docker.io/networkboot/dhcpd:1.3.0 \
  -e -u -x -c 'touch /var/lib/dhcp/dhcpd.leases && eval "echo \"$(cat /opt/dhcpd.conf.template)\"" > /etc/dhcp/dhcpd.conf && dhcpd -d dhcp0'
docker run -d --name dhcp-client \
  --cap-add=NET_RAW \
  --cap-add=NET_ADMIN \
  --volume dhcp-leases-folder:/var/lib/dhclient/ \
  --volume ./dhcp/dhclient.conf:/etc/dhcp/dhclient.conf \
  --network host \
  docker.io/modularitycontainers/dhcp-client:latest \
  dhclient -d -v dhcp0

I created a dummy dhcp0 interface via nmcli.

but the options 143 was not present even though the conf file had them defined.

bhoopesh369 commented 1 month ago

I tried setting up the DHCP server and client in local in the host network but nmcli doesnt show the options eventhough i have set the DHCP config file properly is there any script or something to run them in local? (

@glimchb I had messaged you in slack 2 days before but didn't receive any response

glimchb commented 1 month ago

@glimchb I had messaged you in slack 2 days before but didn't receive any response

i'm traveling, will read soon