utils

package
v0.0.0-...-a68dfee Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 12, 2026 License: Apache-2.0 Imports: 55 Imported by: 0

Documentation

Index

Constants

View Source
const MaxDecompressedContentSize = 1024 * 1024 * 1024 // 1 GB

MaxDecompressedContentSize is the maximum size of a file that can be written to disk after decompression. This is to prevent a DoS attack by unpacking a compressed file that is too big to be decompressed.

Variables

View Source
var EveSSHCommonArgs = []string{
	"-o", "IdentitiesOnly=yes",
	"-o", "ConnectTimeout=5",
	"-o", "StrictHostKeyChecking=no",
	"-o", "UserKnownHostsFile=/dev/null",
}

EveSSHCommonArgs defines common SSH client options used when connecting to EVE devices during tests. These options enforce non-interactive operation, use only the specified identity key, apply a short connection timeout, and disable host key verification to simplify ephemeral test environments.

Functions

func CertToPEM

func CertToPEM(cert *x509.Certificate) []byte

CertToPEM returns the PEM encoding of the certificate.

func ConnectTapToBridge

func ConnectTapToBridge(bridgeName, tapName string) error

ConnectTapToBridge attaches a TAP interface to a Linux bridge by setting the bridge as the TAP interface's master.

func ContainerUsingHostNetwork

func ContainerUsingHostNetwork() bool

ContainerUsingHostNetwork tries to determine if this process is running inside the host network namespace, rather than in the container's own network namespace.

func ConvertToZCert

func ConvertToZCert(cert *x509.Certificate, certType certs.ZCertType) *certs.ZCert

ConvertToZCert converts X.509 certificate to ZCert proto message.

func CopyFile

func CopyFile(src string, dst string) (err error)

CopyFile copy file from src to dst with same permission

func CopyFolder

func CopyFolder(source, destination string) error

CopyFolder from source to destination

func CreateBridge

func CreateBridge(name string, addrs []*net.IPNet, groupFwdMask uint16) error

CreateBridge creates a Linux bridge with the given name, brings it up, and assigns the specified IP addresses to it. IPs can be IPv4 or IPv6.

func CreateCipherCtx

func CreateCipherCtx(cfg *CryptoConfig) (*evecommon.CipherContext, error)

CreateCipherCtx constructs a CipherContext using certificate hashes to derive a deterministic context identifier and encryption parameters.

func CreateDummyInterface

func CreateDummyInterface(name string, ips []net.IPNet) error

CreateDummyInterface creates a dummy interface with the given name and assigns the provided IP addresses. Each IP should include the CIDR mask (/32 for IPv4, /128 for IPv6).

func CreateTUN

func CreateTUN(name string) (*os.File, error)

CreateTUN creates a new TUN (network tunnel) interface with the specified name. The interface is configured in TUN mode (no packet information header) and opened for read/write access via /dev/net/tun.

The caller is responsible for configuring IP addresses, MTU, and routes, as well as closing the returned file descriptor when no longer needed.

See: https://www.kernel.org/doc/Documentation/networking/tuntap.txt

func CreateTap

func CreateTap(name string) error

CreateTap creates a TAP interface and brings it UP.

func DecryptBlock

func DecryptBlock(cipher *evecommon.CipherBlock,
	cfg *CryptoConfig) (*evecommon.EncryptionBlock, error)

DecryptBlock decrypts a CipherBlock and unmarshals it into an EncryptionBlock.

func DeleteBridge

func DeleteBridge(name string) error

DeleteBridge brings a bridge DOWN and deletes it.

func DeleteTap

func DeleteTap(name string) error

DeleteTap deletes a TAP interface.

func ECDSAPrivateKeyToPEM

func ECDSAPrivateKeyToPEM(key *ecdsa.PrivateKey) ([]byte, error)

ECDSAPrivateKeyToPEM returns the PEM encoding of an ECDSA private key in PKCS#8 format.

func EVEDockerImageName

func EVEDockerImageName(ref *api.ImageRef) (string, error)

EVEDockerImageName converts a EVE's ImageRef into a Docker image name of the form: <Repo>:<Version>-<hypervisor>-<arch> Returns an error if any required field is missing or unknown.

func EncryptBlock

EncryptBlock serializes and encrypts an EncryptionBlock using the provided CryptoConfig and CipherContext.

func ExtractFromDockerImage

func ExtractFromDockerImage(ctx context.Context, log *logrus.Entry,
	imageName, localPath, containerPath string) error

ExtractFromDockerImage extracts a file or directory from a Docker image without running it. It creates a temporary container, copies the specified path from it, and then removes the container. Returns an error if any step fails. The temporary container is always removed, even if extraction fails.

Parameters:

  • ctx: Context for cancellation and timeout control.
  • log: Logrus entry used for structured logging.
  • imageName: Name of the Docker image to extract from.
  • localPath: Destination path on the host where the extracted content should be written.
  • containerPath: Path inside the image (container filesystem) to extract.

func ExtractFromTar

func ExtractFromTar(u io.Reader, destination string) error

ExtractFromTar extracts files from a tar reader into the destination directory

func FindUnusedPort

func FindUnusedPort(hostIP net.IP) (uint16, error)

FindUnusedPort picks a random unused TCP port on the given host IP by probing it.

func FuncNameFromStackTrace

func FuncNameFromStackTrace(depth int) string

FuncNameFromStackTrace returns the name of the function at the given call stack depth. Parameters:

depth - the number of stack frames to skip:
        depth 0 = FuncNameFromStackTrace itself
        depth 1 = its caller
        depth 2 = caller's caller, etc.

func GenCARoot

func GenCARoot() (*x509.Certificate, *rsa.PrivateKey, error)

GenCARoot generates a self-signed RSA root CA certificate.

func GenServerCertElliptic

func GenServerCertElliptic(
	caCert *x509.Certificate, caKey *rsa.PrivateKey, serial *big.Int,
	ip []net.IP, dns []string, cn string,
) (*x509.Certificate, *ecdsa.PrivateKey, error)

GenServerCertElliptic generates an ECDSA server certificate signed by the given CA.

func GenerateMAC

func GenerateMAC(devName, ifaceName string) net.HardwareAddr

GenerateMAC returns a deterministic, locally administered, unicast MAC address derived from the device name and interface name.

The MAC is generated by hashing stable identifiers to ensure that:

  • the same device/interface pair always receives the same MAC,
  • MAC addresses remain consistent across restarts,
  • collisions are highly unlikely,
  • the address does not conflict with real hardware.

The locally administered bit is set and the multicast bit is cleared to guarantee the MAC is valid for use in virtualized environments.

func GetDefaultGateway

func GetDefaultGateway(family int) (net.IP, netlink.Link, error)

GetDefaultGateway returns the default gateway IP address and the output interface.

func GetDockerAuthPlain

func GetDockerAuthPlain(log *logrus.Entry, fqdn string) (string, string, error)

GetDockerAuthPlain returns the Docker registry username and password for a given registry FQDN. It reads credentials from the local Docker configuration and returns an error if none are found.

func GetDockerImageSizeBytes

func GetDockerImageSizeBytes(ctx context.Context, imageName string) (int64, error)

GetDockerImageSizeBytes returns the size of the given image in bytes.

func GetEgressInterfaceForIP

func GetEgressInterfaceForIP(ip net.IP) (string, error)

GetEgressInterfaceForIP returns the output interface name for the given destination IP.

func GetFirstHostIP

func GetFirstHostIP(subnet *net.IPNet) net.IP

GetFirstHostIP returns the IP address that should be assigned to the bridge or used as the default gateway. For IPv4 subnets, returns subnet network address + 1 (skips network address). For IPv6 subnets, returns the subnet prefix address itself (valid unicast address).

func GetInterfaceIPs

func GetInterfaceIPs(ifaceName string) ([]net.IP, error)

GetInterfaceIPs returns all IP addresses assigned to the given interface.

func GetLastHostIP

func GetLastHostIP(subnet *net.IPNet) net.IP

GetLastHostIP returns the last usable host IP address within the given subnet. For IPv4 subnets, this is the address immediately before the broadcast address (i.e. network | ^mask - 1). For IPv6 subnets, where there is no broadcast address, this returns the highest address in the subnet (network | ^mask).

func GetNextIP

func GetNextIP(ip net.IP) net.IP

GetNextIP returns the next IP in sequence.

func GetPrevIP

func GetPrevIP(ip net.IP) net.IP

GetPrevIP returns the previous IP in sequence.

func GetSubnetPrefixLen

func GetSubnetPrefixLen(subnet *net.IPNet) uint

GetSubnetPrefixLen returns the prefix length (number of leading 1 bits) of the given subnet's mask.

func HaveDockerImage

func HaveDockerImage(ctx context.Context, log *logrus.Entry, image string) (bool, error)

HaveDockerImage checks if a Docker image exists locally. Returns true if the image exists, false if not, and an error if the check itself fails.

func IsErrDockerImageNotFound

func IsErrDockerImageNotFound(err error) bool

IsErrDockerImageNotFound returns true if err indicates that a Docker image does not exist in the local Docker daemon (i.e. "No such image").

func LoadDockerImageFromReader

func LoadDockerImageFromReader(ctx context.Context, log *logrus.Entry, r io.Reader) error

LoadDockerImageFromReader loads a Docker image into the local Docker daemon from a streaming gzip-compressed tar archive. The provided reader must yield data equivalent to the output of:

docker save <image> | gzip

Image data is consumed incrementally and decompressed on the fly, allowing large images to be loaded without buffering the entire archive in memory.

func NewIPNet

func NewIPNet(ip net.IP, subnet *net.IPNet) *net.IPNet

NewIPNet combines a given IP and subnet into net.IPNet. Returns nil if either the IP or subnet is nil.

func OutputCertAndKey

func OutputCertAndKey(
	crt *x509.Certificate, key any, certFile string, keyFile string,
) error

OutputCertAndKey writes an X.509 certificate and private key to disk in PEM format.

func PrepareAuthContainer

func PrepareAuthContainer(payload []byte, signingCert *x509.Certificate,
	signingKey *ecdsa.PrivateKey) (*auth.AuthContainer, error)

PrepareAuthContainer wraps payload in an AuthContainer signed with the given ECDSA key. It computes a SHA-256 hash of the payload, signs that hash, and records the SHA-256 fingerprint of the signing certificate so the receiver can look up the certificate and verify the signature.

func PullDockerImage

func PullDockerImage(ctx context.Context, log *logrus.Entry, imageName string) error

PullDockerImage ensures a Docker image is available locally by pulling it if necessary. If the image already exists, the function returns immediately.

func RandomDeviceSerial

func RandomDeviceSerial(length int) (string, error)

RandomDeviceSerial returns a random alphanumeric device serial number. The serial contains only letters and digits (no special characters) and is suitable for use as a device identifier.

func ReEncryptCipherData

func ReEncryptCipherData(holder CipherDataHolder, oldCfg, newCfg *CryptoConfig,
	cipherCtx *evecommon.CipherContext) error

ReEncryptCipherData decrypts cipher data using the old CryptoConfig and re-encrypts it using the new CryptoConfig and CipherContext.

func ResolveFile

func ResolveFile(path string) (string, error)

ResolveFile returns the absolute path of the given file after verifying that it exists and is accessible. It returns an error if the path is empty, cannot be resolved, or does not exist.

func RunCommandForeground

func RunCommandForeground(name string, args []string, opts ...CommandOpt) (err error)

RunCommandForeground runs a command in the foreground, attaching its stdout and stderr to the current process and optionally applying command options. The command is terminated if the current process receives a termination signal (SIGINT, SIGTERM, SIGQUIT, or SIGHUP).

func RunDockerCommand

func RunDockerCommand(ctx context.Context, log *logrus.Entry, image string, command string,
	volumeMap map[string]string, platform string) (result string, err error)

RunDockerCommand executes a Docker container using the specified image, command, and bind-mounted volumes, then returns the combined stdout/stderr output.

Parameters:

  • ctx: Context used for cancellation and timeouts.
  • log: Logrus entry for structured logging.
  • image: Docker image to run.
  • command: Shell command string to execute inside the container.
  • volumeMap: Mapping of container paths (keys) to host paths (values) that will be mounted as bind volumes.
  • platform: Optional platform (e.g., "linux/arm64" or "linux/amd64") to run the container under. If empty, the host's default platform is used.

Returns the container output as a string. If any Docker API call fails, an error is returned. Even if cleanup fails, the output (if available) is still returned.

func RunPipeProxy

func RunPipeProxy(ctx context.Context, log *logrus.Entry, proxyName string,
	pipe1, pipe2 Pipe)

RunPipeProxy connects two Pipe instances and forwards data between them bidirectionally. Data received on one pipe is sent to the other, and vice versa.

The function runs two concurrent goroutines—one for each direction—and returns when either direction ends (due to closure or error).

func RunningInContainer

func RunningInContainer() bool

RunningInContainer returns true if the process is likely running inside a container. This is determined by checking for the presence of "/.dockerenv" (Docker-specific) and "/run/.containerenv" (Podman-specific).

func SplitIPv4Subnet

func SplitIPv4Subnet(subnet *net.IPNet) (*net.IPNet, *net.IPNet, error)

SplitIPv4Subnet splits an IPv4 subnet into two equal subnets.

func StreamDockerImageGzip

func StreamDockerImageGzip(ctx context.Context, imageName string) (io.ReadCloser, error)

StreamDockerImageGzip exports a Docker image from the local Docker daemon and returns a streaming reader that produces a gzip-compressed tar archive of the image. The returned ReadCloser streams the equivalent of:

docker save <imageName> | gzip

Data is produced lazily and streamed directly from the Docker daemon, avoiding loading the full image into memory. The caller must read the stream until EOF and close it to release underlying resources.

func ValidatePEMCerts

func ValidatePEMCerts(pemData []byte, expectSingle bool) ([]*pem.Block, error)

ValidatePEMCerts parses PEM-encoded certificates and validates them as X.509. If expectSingle is true, exactly one PEM block is expected; otherwise multiple PEM blocks are allowed (e.g., for proxy or V2 TLS certs).

func ValidatePEMPrivateKeyECDSA

func ValidatePEMPrivateKeyECDSA(pemData []byte) error

ValidatePEMPrivateKeyECDSA parses and validates a PEM-encoded ECDSA private key. Exactly one PEM block must be present. The key may be encoded either as PKCS#8 ("PRIVATE KEY") or legacy EC ("EC PRIVATE KEY").

Types

type CipherDataHolder

type CipherDataHolder interface {
	GetCipherData() *evecommon.CipherBlock
}

CipherDataHolder represents an object that contains CipherData.

type CommandOpt

type CommandOpt func(cmd *exec.Cmd)

CommandOpt allows to modify Cmd config.

func SetCommandEnvVars

func SetCommandEnvVars(vars []string) CommandOpt

SetCommandEnvVars sets the given list of key=value strings as the environment variables for the command.

func SetCommandStdin

func SetCommandStdin(stdin string) CommandOpt

SetCommandStdin sets the given string as the standard input for the command.

func SetThisProcessStdin

func SetThisProcessStdin() CommandOpt

SetThisProcessStdin configures the command to inherit the current process's standard input (stdin). This is typically used for interactive commands that require user input.

type CryptoConfig

type CryptoConfig struct {
	ControllerEncCertHash []byte
	DevCertHash           []byte
	SymmetricKey          []byte
}

CryptoConfig holds cryptographic material derived from device and controller certificates, including certificate hashes and a shared symmetric key.

func NewCryptoConfig

func NewCryptoConfig(devECDHCert, controllerECDHCert *x509.Certificate,
	controllerECDHKey *ecdsa.PrivateKey) (*CryptoConfig, error)

NewCryptoConfig creates a CryptoConfig by hashing the device and controller certificates and deriving a symmetric key using ECDH between the device certificate's public key and the controller's private key.

type DataGetter

type DataGetter interface {
	GetData() []byte
}

DataGetter is a constraint for gRPC response types that can be used with GrpcPipe. Any response type must implement GetData() to allow the pipe to extract the payload as a byte slice.

type GrpcClientPipe

type GrpcClientPipe[Req any, Res any] struct {
	MakeRequest func(data []byte) *Req
	Stream      grpc.BidiStreamingClient[Req, Res]
}

GrpcClientPipe turns client's gRPC stream into Pipe. Res must implement DataGetter. We cannot enforce this at compile time using DataGetter instead of "any" because of pointer/value mismatches between grpc.BidiStreamingClient and the protobuf-generated response type.

func (GrpcClientPipe[Req, Res]) Name

func (p GrpcClientPipe[Req, Res]) Name() string

Name of the pipe.

func (GrpcClientPipe[Req, Res]) Recv

func (p GrpcClientPipe[Req, Res]) Recv() ([]byte, error)

Recv receives data from the server.

func (GrpcClientPipe[Req, Res]) Send

func (p GrpcClientPipe[Req, Res]) Send(data []byte) (int, error)

Send sends data to the server.

type GrpcServerPipe

type GrpcServerPipe[Req any, Res any] struct {
	MakeResponse func(data []byte) *Res
	Stream       grpc.BidiStreamingServer[Req, Res]
}

GrpcServerPipe turns server's gRPC stream into Pipe. Req must implement DataGetter. We cannot enforce this at compile time using DataGetter instead of "any" because of pointer/value mismatches between grpc.BidiStreamingClient and the protobuf-generated response type.

func (GrpcServerPipe[Req, Res]) Name

func (p GrpcServerPipe[Req, Res]) Name() string

Name of the pipe.

func (GrpcServerPipe[Req, Res]) Recv

func (p GrpcServerPipe[Req, Res]) Recv() ([]byte, error)

Recv receives data from the client.

func (GrpcServerPipe[Req, Res]) Send

func (p GrpcServerPipe[Req, Res]) Send(data []byte) (int, error)

Send sends data to the client.

type Pipe

type Pipe interface {
	// Name returns a human-readable identifier for the pipe, used only for logging.
	Name() string

	// Recv reads data from the pipe and returns the received bytes.
	// It may block until data becomes available or an error occurs.
	// If the connection is closed gracefully, it should return io.EOF.
	Recv() (data []byte, err error)

	// Send writes data to the pipe and returns the number of bytes written.
	// It may block until the data is fully transmitted or an error occurs.
	Send(data []byte) (n int, err error)
}

Pipe represents a bidirectional data channel that can send and receive arbitrary byte slices. It abstracts a transport layer such as a TCP connection, a Unix socket, gRPC stream, etc.

type ReadWriterPipe

type ReadWriterPipe struct {
	PipeName string
	RW       io.ReadWriter
	Buf      []byte
}

ReadWriterPipe turns io.ReadWriter into Pipe.

func (ReadWriterPipe) Name

func (p ReadWriterPipe) Name() string

Name of the pipe.

func (ReadWriterPipe) Recv

func (p ReadWriterPipe) Recv() (data []byte, err error)

Recv receives data from the tun device.

func (ReadWriterPipe) Send

func (p ReadWriterPipe) Send(data []byte) (n int, err error)

Send sends data to the tun device.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL