Skip to content

nemith/netconf

Repository files navigation

Go netconf client library

Go Reference Report Card Validate coverage

A performant and complete implementation of the NETCONF network device management protocol in Go.

Like Go itself, only the latest two Go versions are tested and supported (Go 1.23 or Go 1.24).

NOTICE: This library has a pretty stable API however pre-1.0.0 means that there may be some minor renames and changes to the API on the road to stabilization. Release notes should include the changes required. Once 1.0.0 gets released the API will only change in major versions.

Installation

go get nemith.io/netconf

Quick Start

SSH Connection with get-config

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"golang.org/x/crypto/ssh"
	"nemith.io/netconf"
	"nemith.io/netconf/rpc"
	ncssh "nemith.io/netconf/transport/ssh"
)

func main() {
	// Configure SSH client
	config := &ssh.ClientConfig{
		User: "admin",
		Auth: []ssh.AuthMethod{
			ssh.Password("secret"),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // Don't use in production
	}

	// Connect with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	transport, err := ncssh.Dial(ctx, "tcp", "router.example.com:830", config)
	if err != nil {
		log.Fatalf("failed to connect: %v", err)
	}
	defer transport.Close()

	// Create NETCONF session
	session, err := netconf.NewSession(transport)
	if err != nil {
		log.Fatalf("failed to create session: %v", err)
	}
	defer session.Close(context.Background())

	// Get the running configuration
	cfg, err := rpc.GetConfig{Source: rpc.Running}.Exec(ctx, session)
	if err != nil {
		log.Fatalf("get-config failed: %v", err)
	}

	fmt.Printf("Running config:\n%s\n", cfg)
}

NETCONF Notifications

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"golang.org/x/crypto/ssh"
	"nemith.io/netconf"
	"nemith.io/netconf/rpc"
	ncssh "nemith.io/netconf/transport/ssh"
)

func main() {
	config := &ssh.ClientConfig{
		User:            "admin",
		Auth:            []ssh.AuthMethod{ssh.Password("secret")},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	ctx := context.Background()

	transport, err := ncssh.Dial(ctx, "tcp", "router.example.com:830", config)
	if err != nil {
		log.Fatal(err)
	}
	defer transport.Close()

	// Create session with notification handler
	session, err := netconf.NewSession(transport,
		netconf.WithNotifHandlerFunc(func(ctx context.Context, msg *netconf.Message) {
			defer msg.Close()

			var notif netconf.Notification
			if err := msg.Decode(&notif); err != nil {
				log.Printf("failed to decode notification: %v", err)
				return
			}

			fmt.Printf("[%s] Notification received\n", notif.EventTime.Format(time.RFC3339))
		}),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close(ctx)

	// Subscribe to notifications
	if err := rpc.CreateSubscription{}.Exec(ctx, session); err != nil {
		log.Fatalf("failed to subscribe: %v", err)
	}

	fmt.Println("Subscribed to notifications. Press Ctrl+C to exit.")

	// Keep the program running to receive notifications
	select {}
}

RFC Support

RFC Support
RFC6241 Network Configuration Protocol (NETCONF) ✅ supported
RFC6242 Using the NETCONF Protocol over Secure Shell (SSH) ✅ supported
RFC7589 Using the NETCONF Protocol over Transport Layer Security (TLS) ✅ supported
RFC5277 NETCONF Event Notifications ✅ supported
RFC5717 Partial Lock Remote Procedure Call (RPC) for NETCONF ✅ supported
RFC8071 NETCONF Call Home and RESTCONF Call Home 💡 planned
RFC6243 With-defaults Capability for NETCONF ✅ supported
RFC4743 Using NETCONF over the Simple Object Access Protocol (SOAP) ❌ not planned
RFC4744 Using the NETCONF Protocol over the BEEP ❌ not planned

There are other RFC around YANG integration that will be looked at later.

See TODO.md for a list of what is left to implement these features.

Comparison

  • Much cleaner, idomatic API, less dumb I, @nemith, was the original creator of the netconf package and it was my very first Go project and it shows. There are number of questionable API design, code, and a lot of odd un tested bugs. Really this rewrite was created to fix this.
  • No impled vendor ownership Moving the project out of the Juniper organization allowes better control over the project, less implied support (or lack there of), and hopefully more contributions.
  • Transports are implemented in their own packages. This means if you are not using SSH or TLS you don't need to bring in the underlying depdendencies into your binary.
  • Stream based transports. Should mean less memory usage and much less allocation bringing overall performance higher.

Scrapligo driver is quite good and way better than the original juniper project. However this new package concentrates more on RFC correctness and implementing some of the more advanced RFC features like call-home and event notifications. If there is a desire there could be some callaboration with scrapligo in the future.

About

NETCONF implementation in Go.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages