Skip to content

Commit

Permalink
feat: implement landing page for the discovery service
Browse files Browse the repository at this point in the history
Landing page is served on a different port for easier ingress
configuration.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
  • Loading branch information
smira committed Oct 11, 2021
1 parent b579076 commit 95593b8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
23 changes: 23 additions & 0 deletions cmd/discovery-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ import (
"google.golang.org/grpc/status"

"github.com/talos-systems/discovery-service/api/v1alpha1/server/pb"
"github.com/talos-systems/discovery-service/internal/landing"
_ "github.com/talos-systems/discovery-service/internal/proto"
"github.com/talos-systems/discovery-service/internal/state"
"github.com/talos-systems/discovery-service/pkg/server"
)

var (
listenAddr = ":3000"
landingAddr = ":3001"
metricsAddr = ":2122"
debugAddr = ":2123"
devMode = false
Expand All @@ -47,6 +49,7 @@ var (

func init() {
flag.StringVar(&listenAddr, "addr", listenAddr, "addr on which to listen")
flag.StringVar(&landingAddr, "landing-addr", landingAddr, "addr on which to listen for landing page")
flag.StringVar(&metricsAddr, "metrics-addr", metricsAddr, "prometheus metrics listen addr")
flag.BoolVar(&devMode, "debug", devMode, "enable debug mode")
flag.DurationVar(&gcInterval, "gc-interval", gcInterval, "garbage collection interval")
Expand Down Expand Up @@ -143,6 +146,11 @@ func run(ctx context.Context, logger *zap.Logger) error {
return fmt.Errorf("failed to listen: %w", err)
}

landingLis, err := net.Listen("tcp", landingAddr)
if err != nil {
return fmt.Errorf("failed to listen: %w", err)
}

s := grpc.NewServer(serverOptions...)
pb.RegisterClusterServer(s, srv)

Expand All @@ -160,6 +168,10 @@ func run(ctx context.Context, logger *zap.Logger) error {
Handler: &metricsMux,
}

landingServer := http.Server{
Handler: landing.Handler(),
}

eg, ctx := errgroup.WithContext(ctx)

eg.Go(func() error {
Expand All @@ -172,6 +184,16 @@ func run(ctx context.Context, logger *zap.Logger) error {
return nil
})

eg.Go(func() error {
logger.Info("landing server starting", zap.Stringer("address", landingLis.Addr()))

if err := landingServer.Serve(landingLis); err != nil && !errors.Is(err, http.ErrServerClosed) {
return fmt.Errorf("failed to serve: %w", err)
}

return nil
})

eg.Go(func() error {
logger.Info("metrics starting", zap.String("address", metricsServer.Addr))

Expand All @@ -189,6 +211,7 @@ func run(ctx context.Context, logger *zap.Logger) error {
defer shutdownCancel()

s.GracefulStop()
landingServer.Shutdown(ctx) //nolint:errcheck
metricsServer.Shutdown(shutdownCtx) //nolint:errcheck

return nil
Expand Down
47 changes: 47 additions & 0 deletions internal/landing/html/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Discovery Service</title>
</head>
<body>
<h1>What is this IP address?</h1>

<p>This is the Kubernetes cluster Member Discovery Service run by <a href="https://www.siderolabs.com/kubespan/">Sidero Labs</a>.</p>

<p>
If you see traffic to this IP address, it is from Kubernetes nodes in your organization that are using KubeSpan to coordinate secure, encrypted membership of a Kubernetes cluster.
This service provides back information needed to establish the secure communication channels.
</p>

<p>
All information to and from this service is encrypted, and the service cannot decrypt the data - only the nodes that are part of the same Kubernetes cluster can decrypt it.
</p>

<p>
For more information, see <a href="https://www.siderolabs.com/kubespan/">https://www.siderolabs.com/kubespan/</a>.
</p>

<h2>Details</h2>

<p>
Before sending data to the discovery service, Talos will encrypt the affiliate data with AES-GCM encryption and
separately encrypt endpoints with AES in ECB mode so that endpoints coming from different sources can be deduplicated server-side.
</p>

<p>
Each node submits it's data encrypted plus it submits the endpoints it sees from other peers to the discovery service.
The discovery service aggregates the data, deduplicates the endpoints, and sends updates to each connected peer.
Each peer receives information back about other affiliates from the discovery service, decrypts it and uses it to drive KubeSpan and cluster discovery.
</p>

<p>
Moreover, the discovery service has no peristence.
Data is stored in memory only with a TTL set by the clients (i.e. Talos).
The cluster ID is used as a key to select the affiliates (so that different clusters see different affiliates).
</p>

<p>
To summarize, the discovery service knows the client version, cluster ID, the number of affiliates, some encrypted data for each affiliate, and a list of encrypted endpoints.
</p>
</body>
</html>
28 changes: 28 additions & 0 deletions internal/landing/landing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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 landing provides the HTML landing page.
package landing

import (
"embed"
"io/fs"
"net/http"
)

//go:embed "html/index.html"
var static embed.FS

// Handler returns static landing page handler.
func Handler() http.Handler {
subfs, err := fs.Sub(static, "html")
if err != nil {
panic(err)
}

mux := http.NewServeMux()
mux.Handle("/", http.FileServer(http.FS(subfs)))

return mux
}

0 comments on commit 95593b8

Please sign in to comment.