From 2dba17653dbad27ba0e6056ec28144e6f0636534 Mon Sep 17 00:00:00 2001 From: Bhoopesh Date: Fri, 28 Jun 2024 03:53:39 +0530 Subject: [PATCH] feat: fetch dhcp leases from network-manager via dbus Signed-off-by: Bhoopesh --- docker-compose.yml | 10 ++++ sztp-agent/Dockerfile | 9 ++-- sztp-agent/cmd/daemon.go | 3 -- sztp-agent/cmd/run.go | 3 -- sztp-agent/go.mod | 1 + sztp-agent/go.sum | 2 + sztp-agent/pkg/dhcp/network_manager.go | 60 +++++++++++++++++++++ sztp-agent/pkg/dhcp/network_manager_test.go | 8 +++ sztp-agent/pkg/secureagent/daemon.go | 10 +++- 9 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 sztp-agent/pkg/dhcp/network_manager.go create mode 100644 sztp-agent/pkg/dhcp/network_manager_test.go diff --git a/docker-compose.yml b/docker-compose.yml index 2ecf6c54..ce3817d3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -199,8 +199,10 @@ services: - dhcp-leases-folder:/var/lib/dhclient/ - /etc/os-release:/etc/os-release - /etc/ssh:/etc/ssh + - /var/run/dbus:/var/run/dbus networks: - opi + privileged: true command: ['/opi-sztp-agent', 'daemon', '--dhcp-lease-file', '/var/lib/dhclient/dhclient.leases', '--bootstrap-trust-anchor-cert', '/certs/opi.pem', @@ -243,6 +245,14 @@ services: '--device-end-entity-cert', '/certs/first_my_cert.pem', '--device-private-key', '/certs/first_private_key.pem', '--serial-number', 'first-serial-number'] + agent6: + <<: *agent + privileged: true + command: ['/opi-sztp-agent', 'run', + '--bootstrap-trust-anchor-cert', '/certs/opi.pem', + '--device-end-entity-cert', '/certs/first_my_cert.pem', + '--device-private-key', '/certs/first_private_key.pem', + '--serial-number', 'first-serial-number'] avahi: image: docker.io/flungo/avahi:latest diff --git a/sztp-agent/Dockerfile b/sztp-agent/Dockerfile index c728366b..8a6671ac 100644 --- a/sztp-agent/Dockerfile +++ b/sztp-agent/Dockerfile @@ -12,13 +12,16 @@ RUN go mod download # build an app COPY . . -RUN go build -v -o /opi-sztp-agent && CGO_ENABLED=0 go test -v ./... +RUN CGO_ENABLED=0 go build -v -o /opi-sztp-agent + +# Run tests +RUN go test -v ./... # second stage to reduce image size FROM alpine:3.20 -RUN apk add --no-cache --no-check-certificate curl && rm -rf /var/cache/apk/* +RUN apk add --no-cache --no-check-certificate dbus curl && rm -rf /var/cache/apk/* COPY --from=builder /opi-sztp-agent / -CMD [ "/opi-sztp-agent" ] +CMD ["sh", "-c", "dbus-daemon --system && /opi-sztp-agent"] diff --git a/sztp-agent/cmd/daemon.go b/sztp-agent/cmd/daemon.go index 32250f2e..beaf49b2 100644 --- a/sztp-agent/cmd/daemon.go +++ b/sztp-agent/cmd/daemon.go @@ -37,9 +37,6 @@ func NewDaemonCommand() *cobra.Command { if bootstrapURL != "" && dhcpLeaseFile != "" { return fmt.Errorf("'--bootstrap-url' and '--dhcp-lease-file' are mutualy exclusive") } - if bootstrapURL == "" && dhcpLeaseFile == "" { - return fmt.Errorf("'--bootstrap-url' or '--dhcp-lease-file' is required") - } if dhcpLeaseFile != "" { arrayChecker = append(arrayChecker, dhcpLeaseFile) } diff --git a/sztp-agent/cmd/run.go b/sztp-agent/cmd/run.go index 9ae8899e..c3ba7613 100644 --- a/sztp-agent/cmd/run.go +++ b/sztp-agent/cmd/run.go @@ -37,9 +37,6 @@ func NewRunCommand() *cobra.Command { if bootstrapURL != "" && dhcpLeaseFile != "" { return fmt.Errorf("'--bootstrap-url' and '--dhcp-lease-file' are mutualy exclusive") } - if bootstrapURL == "" && dhcpLeaseFile == "" { - return fmt.Errorf("'--bootstrap-url' or '--dhcp-lease-file' is required") - } if dhcpLeaseFile != "" { arrayChecker = append(arrayChecker, dhcpLeaseFile) } diff --git a/sztp-agent/go.mod b/sztp-agent/go.mod index 91f9be05..5db6148a 100644 --- a/sztp-agent/go.mod +++ b/sztp-agent/go.mod @@ -14,6 +14,7 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/godbus/dbus/v5 v5.1.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jaypipes/pcidb v1.0.0 // indirect github.com/kr/text v0.2.0 // indirect diff --git a/sztp-agent/go.sum b/sztp-agent/go.sum index 74f44cb4..03f38b55 100644 --- a/sztp-agent/go.sum +++ b/sztp-agent/go.sum @@ -15,6 +15,8 @@ github.com/github/smimesign v0.2.0/go.mod h1:iZiiwNT4HbtGRVqCQu7uJPEZCuEE5sfSStt github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho= diff --git a/sztp-agent/pkg/dhcp/network_manager.go b/sztp-agent/pkg/dhcp/network_manager.go new file mode 100644 index 00000000..ec99ed45 --- /dev/null +++ b/sztp-agent/pkg/dhcp/network_manager.go @@ -0,0 +1,60 @@ +/* +SPDX-License-Identifier: Apache-2.0 +Copyright (C) 2022-2023 Intel Corporation +Copyright (c) 2022 Dell Inc, or its subsidiaries. +Copyright (C) 2022 Red Hat. +*/ + +// Package dhcp implements the DHCP client +package dhcp + +import ( + "fmt" + "log" + + "github.com/godbus/dbus/v5" +) + +// GetBootstrapURLViaNetworkManager returns the sztp redirect URL via NetworkManager +func GetBootstrapURLViaNetworkManager() (string, error) { + conn, err := dbus.SystemBus() + if err != nil { + return "", fmt.Errorf("failed to connect to system bus: %v", err) + } + + nm := conn.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager") + + var primaryConnPath dbus.ObjectPath + err = nm.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager", "PrimaryConnection").Store(&primaryConnPath) + if err != nil { + return "", fmt.Errorf("failed to get PrimaryConnection property: %v", err) + } + + connActive := conn.Object("org.freedesktop.NetworkManager", primaryConnPath) + + var dhcpPath dbus.ObjectPath + err = connActive.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.NetworkManager.Connection.Active", "Dhcp4Config").Store(&dhcpPath) + if err != nil { + return "", fmt.Errorf("failed to get Dhcp4Config property: %v", err) + } + + 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 { + return "", fmt.Errorf("failed to get Options property: %v", err) + } + + if variant, ok := options["sztp_redirect_urls"]; ok { + if variant.Signature().String() == "s" { + sztpRedirectURLs := variant.Value().(string) + log.Println(sztpRedirectURLs) + return sztpRedirectURLs, nil + } + log.Println("sztp_redirect_urls is not a string") + return "", fmt.Errorf("sztp_redirect_urls is not a string") + } + + log.Println("sztp_redirect_urls option not found") + return "", fmt.Errorf("sztp_redirect_urls option not found") +} diff --git a/sztp-agent/pkg/dhcp/network_manager_test.go b/sztp-agent/pkg/dhcp/network_manager_test.go new file mode 100644 index 00000000..f8abcd28 --- /dev/null +++ b/sztp-agent/pkg/dhcp/network_manager_test.go @@ -0,0 +1,8 @@ +package dhcp + +import "testing" + +func TestGetBootstrapURLViaNetworkManager(_ *testing.T) { + // TODO: Implement the test + // Simulate the dbus calls +} diff --git a/sztp-agent/pkg/secureagent/daemon.go b/sztp-agent/pkg/secureagent/daemon.go index 9ad0e547..2878321c 100644 --- a/sztp-agent/pkg/secureagent/daemon.go +++ b/sztp-agent/pkg/secureagent/daemon.go @@ -31,6 +31,7 @@ import ( "time" "github.com/github/smimesign/ietf-cms/protocol" + "github.com/opiproject/sztp/sztp-agent/pkg/dhcp" ) const ( @@ -102,8 +103,13 @@ func (a *Agent) getBootstrapURL() error { } a.SetBootstrapURL(extractfromLine(line, `(?m)[^"]*`, 1)) } else { - log.Printf("[ERROR] File " + a.DhcpLeaseFile + " does not exist\n") - return errors.New(" File " + a.DhcpLeaseFile + " does not exist\n") + log.Println("[INFO] File " + a.DhcpLeaseFile + " does not exist, trying to get the URL from NetworkManager") + url, err := dhcp.GetBootstrapURLViaNetworkManager() + if err != nil { + log.Println("[ERROR] ", err.Error()) + return err + } + a.SetBootstrapURL(url) } log.Println("[INFO] Bootstrap URL retrieved successfully: " + a.GetBootstrapURL()) return nil