Utku Ozdemir 5ac9f43e45
feat: start machined earlier & in maintenance mode
Load & start machined earlier and in initialize sequence, so that it is possible to use its API over its unix socket in maintenance mode.

Additionally, do not return features from Version API  if a config is not yet available.

Related to siderolabs/talos#4791.

Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
2023-02-21 12:21:36 +01:00

142 lines
3.7 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package trustd
import (
"context"
"flag"
"fmt"
"log"
"os/signal"
"syscall"
"time"
"github.com/cosi-project/runtime/api/v1alpha1"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"github.com/cosi-project/runtime/pkg/state/protobuf/client"
debug "github.com/siderolabs/go-debug"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"github.com/siderolabs/talos/internal/app/trustd/internal/provider"
"github.com/siderolabs/talos/internal/app/trustd/internal/reg"
"github.com/siderolabs/talos/pkg/grpc/factory"
"github.com/siderolabs/talos/pkg/grpc/middleware/auth/basic"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/resources/secrets"
"github.com/siderolabs/talos/pkg/startup"
)
func runDebugServer(ctx context.Context) {
const debugAddr = ":9983"
debugLogFunc := func(msg string) {
log.Print(msg)
}
if err := debug.ListenAndServe(ctx, debugAddr, debugLogFunc); err != nil {
log.Fatalf("failed to start debug server: %s", err)
}
}
// Main is the entrypoint into trustd.
func Main() {
if err := trustdMain(); err != nil {
log.Fatal(err)
}
}
//nolint:gocyclo
func trustdMain() error {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
defer cancel()
log.SetFlags(log.Lshortfile | log.Ldate | log.Lmicroseconds | log.Ltime)
flag.Parse()
go runDebugServer(ctx)
startup.LimitMaxProcs(constants.TrustdMaxProcs)
var err error
if err = startup.RandSeed(); err != nil {
return fmt.Errorf("startup: %s", err)
}
runtimeConn, err := grpc.Dial("unix://"+constants.TrustdRuntimeSocketPath, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return fmt.Errorf("failed to dial runtime connection: %w", err)
}
stateClient := v1alpha1.NewStateClient(runtimeConn)
resources := state.WrapCore(client.NewAdapter(stateClient))
tlsConfig, err := provider.NewTLSConfig(resources)
if err != nil {
return fmt.Errorf("failed to create remote certificate provider: %w", err)
}
serverTLSConfig, err := tlsConfig.ServerConfig()
if err != nil {
return fmt.Errorf("failed to create OS-level TLS configuration: %w", err)
}
creds := basic.NewTokenCredentialsDynamic(tokenGetter(resources))
networkListener, err := factory.NewListener(
factory.Port(constants.TrustdPort),
)
if err != nil {
return fmt.Errorf("error creating listener: %w", err)
}
networkServer := factory.NewServer(
&reg.Registrator{Resources: resources},
factory.WithDefaultLog(),
factory.WithUnaryInterceptor(creds.UnaryInterceptor()),
factory.ServerOptions(
grpc.Creds(
credentials.NewTLS(serverTLSConfig),
),
),
)
errGroup, ctx := errgroup.WithContext(ctx)
errGroup.Go(func() error {
return networkServer.Serve(networkListener)
})
errGroup.Go(func() error {
<-ctx.Done()
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
defer shutdownCancel()
factory.ServerGracefulStop(networkServer, shutdownCtx)
return nil
})
return errGroup.Wait()
}
func tokenGetter(state state.State) basic.TokenGetterFunc {
return func(ctx context.Context) (string, error) {
osRoot, err := safe.StateGet[*secrets.OSRoot](ctx, state, resource.NewMetadata(secrets.NamespaceName, secrets.OSRootType, secrets.OSRootID, resource.VersionUndefined))
if err != nil {
return "", err
}
return osRoot.TypedSpec().Token, nil
}
}