Ctrl K
ComunidadGuías…

iclient/config_remote.go

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package iclient

import (
	"fmt"
	"slices"
	"strings"

	"github.com/lxc/incus/v7/shared/api"
)

// ConfigRemoteInfo is everything needed to dial one remote, read off disk once.
type ConfigRemoteInfo struct {
	Name string

	// Addrs starts at the remote's last known working address.
	Addrs    []string
	Protocol string
	AuthType string

	// Username and Password reach an "oci" registry, from its credentials
	// helper or else from its address. They are deliberately not left in
	// Addrs, which is logged and formatted into errors.
	Username string
	Password string

	Public    bool
	KeepAlive int
	UserAgent string

	// InsecureSkipVerify accepts any server certificate, for registering
	// against one whose certificate is not known yet.
	InsecureSkipVerify bool

	// TLS material, all empty for a unix-socket-only remote.
	ServerCert        string
	ServerFingerprint string
	ClientCert        string
	ClientKey         string
	ClientCA          string
}

// Unix reports whether every address is the local unix socket.
func (i *ConfigRemoteInfo) Unix() bool {
	return len(i.Addrs) > 0 && !slices.ContainsFunc(i.Addrs, func(addr string) bool {
		return !strings.HasPrefix(addr, "unix:")
	})
}

// RemoteInfos resolves a remote into what it takes to connect to it. An empty
// name means the default remote.
func (c *Config) RemoteInfos(remote string) (*ConfigRemoteInfo, error) {
	if remote == "" {
		remote = c.DefaultRemote
	}

	r, ok := c.Remotes[remote]
	if !ok {
		return nil, fmt.Errorf("%q: %w", remote, ErrConfigRemoteNotFound)
	}

	info := &ConfigRemoteInfo{
		Name:      remote,
		Addrs:     r.rollingAddrs(),
		Protocol:  r.Protocol,
		AuthType:  r.AuthType,
		Public:    r.Public,
		KeepAlive: r.KeepAlive,
		UserAgent: c.UserAgent,
	}

	if len(info.Addrs) == 0 {
		return nil, fmt.Errorf("%q: remote has no address", remote)
	}

	if r.Protocol == "oci" {
		err := c.applyCredentials(remote, r, info)
		if err != nil {
			return nil, err
		}
	}

	// A unix socket carries no TLS; only a private incus remote has a client certificate.
	if info.Unix() {
		return info, nil
	}

	var err error

	info.ServerCert, err = readIfPresent(c.ServerCertPath(remote))
	if err != nil {
		return nil, err
	}

	if r.Protocol != "incus" || r.AuthType == api.AuthenticationMethodOIDC {
		return info, nil
	}

	if r.TLS != nil {
		info.ClientCert, info.ClientKey, info.ClientCA = r.TLS.Certificate, r.TLS.Key, r.TLS.CA

		return info, nil
	}

	certPath, keyPath, caPath := c.clientCertPaths(remote)

	for _, f := range []struct {
		path string
		into *string
	}{
		{certPath, &info.ClientCert},
		{keyPath, &info.ClientKey},
		{caPath, &info.ClientCA},
	} {
		*f.into, err = readIfPresent(f.path)
		if err != nil {
			return nil, err
		}
	}

	return info, nil
}