Files
teleport/lib/web/scripts.go
T
Cam HutchisonandCam Hutchison 432428fc57 fips: Rename IsBoringBinary to IsFIPSBuild throughout (#66346)
* fips: Rename IsBoringBinary to IsFIPSBuild throughout

Rename the function and method `IsBoringBinary` to `IsFIPSBuild`
throughout the code base and change references to boringcrypto to
fips140 or similar. This is part of removing boringcrypto from the
build, replacing it with Go-native FIPS140.

There are still some references to "boring":
* The PingResponse message has a field IsBoring in authservice.proto.
  This cannot be changed without breaking source compatibility in api/
* The example in examples/teleport-usage has an explicit check for the
  boring package to set an AWS FIPS option. This will be changed when
  the actual change to Go-native FIPS is done.
* Rust references to boringsys - this is still used in Rust and will not
  be changed when using Go-native FIPS.
* The actual import of boring to use it. This will be changed when using
  Go-Native FIPS.

This rename is separate from the Go-native FIPS implementation so it can
be backported to keep the branches close, to avoid unnecessary
conflicts.

* fips: Add "crypto/tls/fipsonly" import for boring builds

Import the "crypto/tls/fipsonly" package when building in fips mode.
This import is also done in the Enterprise repo with some rename magic
so that the file the import is in only exists for fips builds. This was
necessary when boringcrypto was only available in a special branch of
the Go toolchain, but has not been necessary since Go 1.19 when
boringcrypto was brought into the proper toolchain.

Moving this here makes the enterprise makefile and fips build simpler.
There is no need to split this now.

The import causes TLS negotiation to reject non-FIPS140 ciphers.

---------

Co-authored-by: Cam Hutchison <camh@xdna.net>
2026-05-02 10:58:23 +00:00

172 lines
6.6 KiB
Go

/*
* Teleport
* Copyright (C) 2025 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package web
import (
"context"
"fmt"
"net/http"
"os"
"strconv"
"github.com/coreos/go-semver/semver"
"github.com/gravitational/trace"
"github.com/julienschmidt/httprouter"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/utils/teleportassets"
"github.com/gravitational/teleport/lib/web/scripts"
)
const (
insecureParamName = "insecure"
groupParamName = "group"
)
// installScriptHandle handles calls for "/scripts/install.sh" and responds with a bash script installing Teleport
// by downloading and running `teleport-update`. This installation script does not start the agent, join it,
// or configure its services. This is handled by the "/scripts/:token/install-*.sh" scripts.
func (h *Handler) installScriptHandle(w http.ResponseWriter, r *http.Request, params httprouter.Params) (any, error) {
// This is a hack because the router is not allowing us to register "/scripts/install.sh", so we use
// the parameter ":token" to match the script name.
// Currently, only "install.sh" is supported.
if params.ByName("token") != "install.sh" {
return nil, trace.NotFound(`Route not found, query "/scripts/install.sh" for the install-only script, or "/scripts/:token/install-node.sh" for the install + join script.`)
}
// TODO(hugoShaka): cache function
opts, err := h.installScriptOptions(r.Context())
if err != nil {
return nil, trace.Wrap(err, "Failed to build install script options")
}
if insecure := r.URL.Query().Get(insecureParamName); insecure != "" {
v, err := strconv.ParseBool(insecure)
if err != nil {
return nil, trace.BadParameter("failed to parse insecure flag %q: %v", insecure, err)
}
opts.Insecure = v
}
if group := r.URL.Query().Get(groupParamName); group != "" {
opts.Group = group
}
script, err := scripts.GetInstallScript(r.Context(), opts)
if err != nil {
h.logger.WarnContext(r.Context(), "Failed to get install script", "error", err)
return nil, trace.Wrap(err, "getting script")
}
w.WriteHeader(http.StatusOK)
if _, err := fmt.Fprintln(w, script); err != nil {
h.logger.WarnContext(r.Context(), "Failed to write install script", "error", err)
}
return nil, nil
}
// installScriptOptions computes the agent installation options based on the proxy configuration and the cluster status.
// This includes:
// - the type of automatic updates
// - the desired version
// - the proxy address (used for updates).
// - the Teleport artifact name and CDN
func (h *Handler) installScriptOptions(ctx context.Context) (scripts.InstallScriptOptions, error) {
const defaultGroup, defaultUpdater = "", ""
version, err := h.autoUpdateResolver.GetVersion(ctx, defaultGroup, defaultUpdater)
if err != nil {
h.logger.WarnContext(ctx, "Failed to get intended agent version", "error", err)
version = teleport.SemVer()
}
// if there's a rollout, we do new autoupdates
_, rolloutErr := h.cfg.AccessPoint.GetAutoUpdateAgentRollout(ctx)
if rolloutErr != nil && !trace.IsNotFound(rolloutErr) && !trace.IsNotImplemented(rolloutErr) {
h.logger.WarnContext(ctx, "Failed to get rollout", "error", rolloutErr)
return scripts.InstallScriptOptions{}, trace.Wrap(err, "failed to check the autoupdate agent rollout state")
}
var autoupdateStyle scripts.AutoupdateStyle
switch {
case rolloutErr == nil:
autoupdateStyle = scripts.UpdaterBinaryAutoupdate
case automaticUpgrades(h.GetClusterFeatures()):
autoupdateStyle = scripts.PackageManagerAutoupdate
default:
autoupdateStyle = scripts.NoAutoupdate
}
var teleportFlavor string
switch h.cfg.Modules.BuildType() {
case modules.BuildEnterprise:
teleportFlavor = types.PackageNameEnt
case modules.BuildOSS, modules.BuildCommunity:
teleportFlavor = types.PackageNameOSS
default:
h.logger.WarnContext(ctx, "Unknown built type, defaulting to the 'teleport' package.", "type", h.cfg.Modules.BuildType())
teleportFlavor = types.PackageNameOSS
}
cdnBaseURL, err := getCDNBaseURL(h.cfg.Modules.BuildType(), version)
if err != nil {
h.logger.WarnContext(ctx, "Failed to get CDN base URL", "error", err)
return scripts.InstallScriptOptions{}, trace.Wrap(err)
}
return scripts.InstallScriptOptions{
AutoupdateStyle: autoupdateStyle,
TeleportVersion: version,
CDNBaseURL: cdnBaseURL,
ProxyAddr: h.PublicProxyAddr(),
TeleportFlavor: teleportFlavor,
FIPS: modules.IsFIPSBuild(),
}, nil
}
// EnvVarCDNBaseURL is the environment variable that allows users to override the Teleport base CDN url used in the installation script.
// Setting this value is required for testing (make production builds install from the dev CDN, and vice versa).
// As we (the Teleport company) don't distribute AGPL binaries, this must be set when using a Teleport OSS build.
// Example values:
// - "https://cdn.teleport.dev" (prod)
// - "https://cdn.cloud.gravitational.io" (dev builds/staging)
const EnvVarCDNBaseURL = "TELEPORT_CDN_BASE_URL"
func getCDNBaseURL(buildType string, version *semver.Version) (string, error) {
// If the user explicitly overrides the CDN base URL, we use it.
if override := os.Getenv(EnvVarCDNBaseURL); override != "" {
return override, nil
}
// If this is an AGPL build, we don't want to automatically install binaries distributed under a more restrictive
// license so we error and ask the user set the CDN URL, either to:
// - the official Teleport CDN if they agree with the community license and meet its requirements
// - a custom CDN where they can store their own AGPL binaries
if buildType == modules.BuildOSS {
return "", trace.BadParameter(
"This proxy is licensed under AGPL but CDN binaries are licensed under the more restrictive Community license. "+
"You can set TELEPORT_CDN_BASE_URL to a custom CDN, or to %q if you are OK with using the Community Edition license.",
teleportassets.CDNBaseURL())
}
return teleportassets.CDNBaseURLForVersion(version), nil
}