# Make targets: # # all : builds all binaries in development mode # full : builds all binaries for PRODUCTION use # release: prepares a release tarball # clean : removes all build artifacts # test : runs tests .DEFAULT_GOAL := all # To update the Teleport version, update VERSION variable: # Naming convention: # Stable releases: "1.0.0" # Pre-releases: "1.0.0-alpha.1", "1.0.0-beta.2", "1.0.0-rc.3" # Master/dev branch: "1.0.0-dev" VERSION=19.0.0-prealpha.2 DOCKER_IMAGE ?= teleport # This directory will be the real path of the directory of the first Makefile in the list. MAKE_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) # If set to 1, webassets are not built. WEBASSETS_SKIP_BUILD ?= 0 # These are standard autotools variables, don't change them please ifneq ("$(wildcard /bin/bash)","") SHELL := /bin/bash -o pipefail endif BUILDDIR ?= build BINDIR ?= /usr/local/bin DATADIR ?= /usr/local/share/teleport ADDFLAGS ?= PWD ?= $(shell pwd) TELEPORT_DEBUG ?= false GITTAG=v$(VERSION) CGOFLAG ?= CGO_ENABLED=1 KUSTOMIZE_NO_DYNAMIC_PLUGIN ?= kustomize_disable_go_plugin_support KUBECTL_VERSION := $(shell go list -m -f '{{.Version}}' k8s.io/kubectl | sed 's/v0/v1/') KUBECTL_SETVERSION := -X k8s.io/component-base/version.gitVersion=$(KUBECTL_VERSION) # RELEASE_DIR is where the release artifacts (tarballs, pacakges, etc) are put. It # should be an absolute directory as it is used by e/Makefile too, from the e/ directory. RELEASE_DIR := $(CURDIR)/$(BUILDDIR)/artifacts GO_LDFLAGS ?= -w -s $(KUBECTL_SETVERSION) # Appending new conditional settings for community build type # When TELEPORT_DEBUG is true, set flags to produce # debugger-friendly builds. ifeq ("$(TELEPORT_DEBUG)","true") BUILDFLAGS ?= $(ADDFLAGS) -gcflags=all="-N -l" -buildvcs=false BUILDFLAGS_TBOT ?= $(ADDFLAGS) -gcflags=all="-N -l" -buildvcs=false BUILDFLAGS_TELEPORT_UPDATE ?= $(ADDFLAGS) -gcflags=all="-N -l" -buildvcs=false else BUILDFLAGS ?= $(ADDFLAGS) -ldflags '$(GO_LDFLAGS)' -trimpath -buildvcs=false BUILDFLAGS_TBOT ?= $(ADDFLAGS) -ldflags '$(GO_LDFLAGS)' -trimpath -buildvcs=false BUILDFLAGS_TELEPORT_UPDATE ?= $(ADDFLAGS) -ldflags '$(GO_LDFLAGS)' -trimpath -buildvcs=false endif GO_ENV_OS := $(shell go env GOOS) OS ?= $(GO_ENV_OS) GO_ENV_ARCH := $(shell go env GOARCH) ARCH ?= $(GO_ENV_ARCH) FIPS ?= RELEASE = teleport-$(GITTAG)-$(OS)-$(ARCH)-bin RELEASE_TOOLS = teleport-tools-$(GITTAG)-$(OS)-$(ARCH)-bin RELEASE_UPDATE = teleport-update-$(GITTAG)-$(OS)-$(ARCH)-bin # If we're building inside the cross-compiling buildbox, include the # cross compilation definitions so we select the correct compilers and # libraries. ifeq ($(BUILDBOX_MODE),cross) include build.assets/buildbox/cross-compile.mk endif # Include common makefile shared between OSS and Ent. include common.mk # FIPS support must be requested at build time. FIPS_MESSAGE := without-FIPS-support ifneq ("$(FIPS)","") FIPS_TAG := fips FIPS_MESSAGE := with-FIPS-support RELEASE = teleport-$(GITTAG)-$(OS)-$(ARCH)-fips-bin GOFIPS140 = v1.0.0 export GOFIPS140 ifeq ($(BUILDBOX_MODE),cross) # We need to set CGO_ENABLED=0 when building rdpclient as the build of # boring-sys builds and runs a Go program as part of its integrity testing. # (https://github.com/google/boringssl/blob/master/crypto/fipsmodule/FIPS.md#integrity-testing) # If CGO_ENABLED=1, this fails for odd reasons (it tries to use the cross # assembler to build ASM for the host). # It also needs to know the cross-compiler sysroot to properly cross-compile. RDPCLIENT_ENV = CGO_ENABLED=0 BORING_BSSL_FIPS_SYSROOT=$(CROSSTOOLNG_SYSROOT) endif endif # Look for the PAM header "security/pam_appl.h" to determine if we should # enable PAM support in teleport. A native build will have it in /usr/include. # Darwin has it in /usr/local/include (SIP prevents us from modifying/creating # it in /usr/include), and the ng buildbox has it in one of the # $(C_INCLUDE_PATH) paths. PAM_HEADER_CANDIDATES := $(subst :, ,$(C_INCLUDE_PATH)) /usr/local/include /usr/include PAM_MESSAGE := without-PAM-support ifneq (,$(wildcard $(addsuffix /security/pam_appl.h,$(PAM_HEADER_CANDIDATES)))) PAM_TAG := pam PAM_MESSAGE := with-PAM-support endif # darwin universal (Intel + Apple Silicon combined) binary support RELEASE_darwin_arm64 = $(RELEASE_DIR)/teleport-$(GITTAG)-darwin-arm64-bin.tar.gz RELEASE_darwin_amd64 = $(RELEASE_DIR)/teleport-$(GITTAG)-darwin-amd64-bin.tar.gz BUILDDIR_arm64 = $(BUILDDIR)/arm64 BUILDDIR_amd64 = $(BUILDDIR)/amd64 # TARBINS is the path of the binaries in the release tarballs TARBINS = $(addprefix teleport/,$(BINS)) # Check if rust and cargo are installed before compiling CHECK_CARGO := $(shell cargo --version 2>/dev/null) CHECK_RUST := $(shell rustc --version 2>/dev/null) RUST_TARGET_ARCH ?= $(CARGO_TARGET_$(OS)_$(ARCH)) CARGO_TARGET_darwin_amd64 := x86_64-apple-darwin CARGO_TARGET_darwin_arm64 := aarch64-apple-darwin CARGO_TARGET_linux_arm := arm-unknown-linux-gnueabihf CARGO_TARGET_linux_arm64 := aarch64-unknown-linux-gnu CARGO_TARGET_linux_386 := i686-unknown-linux-gnu CARGO_TARGET_linux_amd64 := x86_64-unknown-linux-gnu CARGO_TARGET_windows_amd64 := x86_64-pc-windows-gnu CARGO_TARGET := --target=$(RUST_TARGET_ARCH) CARGO_WASM_TARGET := wasm32-unknown-unknown # If set to 1, then we don't build the desktop access RDP client # or the RDP decoder for tsh. RDPCLIENT_SKIP_BUILD ?= 0 # Enable Rust RDP support? with_rdpclient := no RDPCLIENT_MESSAGE := without-Windows-RDP-client ifeq ($(RDPCLIENT_SKIP_BUILD),0) ifneq ($(CHECK_RUST),) ifneq ($(CHECK_CARGO),) is_fips_on_arm64 := no ifneq ("$(FIPS)","") ifeq ("$(ARCH)","arm64") is_fips_on_arm64 := yes endif endif # Do not build RDP client on 32-bit ARM or 386, or for FIPS builds on arm64. ifneq ("$(ARCH)","arm") ifneq ("$(ARCH)","386") ifneq ("$(is_fips_on_arm64)","yes") with_rdpclient := yes RDPCLIENT_MESSAGE := with-Windows-RDP-client RDPCLIENT_TAG := desktop_access_rdp TSH_RDP_DECODER_TAG := rust_rdp_decoder endif endif endif endif endif endif # Set C_ARCH for building libfido2 and dependencies. ARCH is the Go # architecture which uses different names for architectures than C # uses. Export it for the build.assets/build-fido2-macos.sh script. C_ARCH_amd64 = x86_64 C_ARCH = $(or $(C_ARCH_$(ARCH)),$(ARCH)) export C_ARCH # Enable libfido2 for testing? # Eagerly enable if we detect the package, we want to test as much as possible. ifeq ("$(shell pkg-config libfido2 2>/dev/null; echo $$?)", "0") LIBFIDO2_TEST_TAG := libfido2 ifeq ($(FIDO2),) FIDO2 ?= dynamic endif endif # Build tsh against libfido2? # FIDO2=yes and FIDO2=static enable static libfido2 builds. # FIDO2=dynamic enables dynamic libfido2 builds. LIBFIDO2_MESSAGE := without-libfido2 ifneq (, $(filter $(FIDO2), yes static)) LIBFIDO2_MESSAGE := with-libfido2 LIBFIDO2_BUILD_TAG := libfido2 libfido2static else ifeq ("$(FIDO2)", "dynamic") LIBFIDO2_MESSAGE := with-libfido2 LIBFIDO2_BUILD_TAG := libfido2 endif # Enable Touch ID builds? # Only build if TOUCHID=yes to avoid issues when cross-compiling to 'darwin' # from other systems. TOUCHID_MESSAGE := without-Touch-ID ifeq ("$(TOUCHID)", "yes") TOUCHID_MESSAGE := with-Touch-ID TOUCHID_TAG := touchid endif # Enable VNet daemon? # With VNETDAEMON=yes, tsh uses a Launch Daemon to start VNet. # This requires a signed and bundled tsh. VNETDAEMON_MESSAGE := without-VNet-daemon ifeq ("$(VNETDAEMON)", "yes") VNETDAEMON_MESSAGE := with-VNet-daemon VNETDAEMON_TAG := vnetdaemon endif # Enable PIV test packages for testing. # This test tag should never be used for builds/releases, only tests. PIV_TEST_TAG := pivtest # enable PIV package for linting. PIV_LINT_TAG := piv # Build teleport/api with PIV? This requires the libpcsclite library for linux. # # PIV=yes and PIV=static enable static piv builds. This is used by the build # process to link a static library of libpcsclite for piv-go to connect to. # # PIV=dynamic enables dynamic piv builds. This can be used for local # builds and runs utilizing a dynamic libpcsclite library - `apt get install libpcsclite-dev` PIV_MESSAGE := without-PIV-support ifneq (, $(filter $(PIV), yes static dynamic)) PIV_MESSAGE := with-PIV-support PIV_BUILD_TAG := piv ifneq ("$(PIV)", "dynamic") # Link static pcsc libary. By default, piv-go will look for the dynamic library. # https://github.com/go-piv/piv-go/blob/master/piv/pcsc_unix.go#L23 STATIC_LIBS += -lpcsclite STATIC_LIBS_TSH += -lpcsclite endif endif SESSIONHELPER_EMBED_TAG := SESSIONHELPER_MESSAGE := without-session-helper ifeq ($(OS),linux) SESSIONHELPER_EMBED_TAG = sessionhelper_embed SESSIONHELPER_MESSAGE := with-session-helper endif # Reproducible builds are only available on select targets, and only when OS=linux. REPRODUCIBLE ?= ifneq ("$(OS)","linux") REPRODUCIBLE = no endif # On Windows only build tsh. On all other platforms build teleport, tctl, # and tsh. BINS_default = teleport tctl tsh tbot fdpass-teleport teleport-update BINS_darwin = teleport tctl tsh tbot fdpass-teleport BINS_windows = tsh tctl BINS = $(or $(BINS_$(OS)),$(BINS_default)) BINARIES = $(addprefix $(BUILDDIR)/,$(BINS)) UPDATE_BINARIES = $(addprefix $(BUILDDIR)/,teleport-update) # Joins elements of the list in arg 2 with the given separator. # 1. Element separator. # 2. The list. EMPTY := SPACE := $(EMPTY) $(EMPTY) join-with = $(subst $(SPACE),$1,$(strip $2)) # Separate TAG messages into comma-separated WITH and WITHOUT lists for readability. COMMA := , MESSAGES := $(PAM_MESSAGE) $(FIPS_MESSAGE) $(BPF_MESSAGE) $(RDPCLIENT_MESSAGE) $(LIBFIDO2_MESSAGE) $(TOUCHID_MESSAGE) $(PIV_MESSAGE) $(VNETDAEMON_MESSAGE) $(SESSIONHELPER_MESSAGE) WITH := $(subst -," ",$(call join-with,$(COMMA) ,$(subst with-,,$(filter with-%,$(MESSAGES))))) WITHOUT := $(subst -," ",$(call join-with,$(COMMA) ,$(subst without-,,$(filter without-%,$(MESSAGES))))) RELEASE_MESSAGE := "Building with GOOS=$(OS) GOARCH=$(ARCH) REPRODUCIBLE=$(REPRODUCIBLE) and with $(WITH) and without $(WITHOUT)." # On platforms that support reproducible builds, ensure the archive is created in a reproducible manner. TAR_FLAGS ?= ifeq ("$(REPRODUCIBLE)","yes") TAR_FLAGS = --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2015-03-02' --format=gnu endif VERSRC = gitref.go api/version.go KUBECONFIG ?= TEST_KUBE ?= export # This unexport statement is required for make to work with the `-e` flag. # With -e, the first Makefile sets HELMJANITOR=$$(go tool ...), # passes HELMJANITOR=$(go tool) to the child make process. # Because of the `-e` flag it takes precedence over the child's make definition # of HELMJANITOR and breaks environment variable expansion. # To avoid breaking other parts of the release pipeline, the easiest fix is to # unexport HELMJANITOR so the child uses the definition from its Makefile. unexport HELMJANITOR export KUBECONFIG export TEST_KUBE TEST_LOG_DIR ?= ${abspath ./test-logs} # Set CGOFLAG and BUILDFLAGS as needed for the OS/ARCH. ifeq ("$(OS)","linux") ifeq ("$(ARCH)","arm64") ifneq ($(BUILDBOX_MODE),cross) ifeq (,$(IS_NATIVE_BUILD)) CGOFLAG += CC=aarch64-linux-gnu-gcc endif endif else ifeq ("$(ARCH)","arm") CGOFLAG = CGO_ENABLED=1 # ARM builds need to specify the correct C compiler ifneq ($(BUILDBOX_MODE),cross) ifeq (,$(IS_NATIVE_BUILD)) CC=arm-linux-gnueabihf-gcc endif endif # Add -debugtramp=2 to work around 24 bit CALL/JMP instruction offset. # Add "-extldflags -Wl,--long-plt" to avoid ld assertion failure on large binaries GO_LDFLAGS += -extldflags=-Wl,--long-plt -debugtramp=2 endif endif # OS == linux ifeq ("$(OS)-$(ARCH)","darwin-arm64") # Temporary link flags due to changes in Apple's linker # https://github.com/golang/go/issues/67854 GO_LDFLAGS += -extldflags=-ld_classic endif # Windows requires extra parameters to cross-compile with CGO. ifeq ("$(OS)","windows") ARCH ?= amd64 ifneq ("$(ARCH)","amd64") $(error "Building for windows requires ARCH=amd64") endif CGOFLAG = CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ BUILDFLAGS = $(ADDFLAGS) -ldflags '-w -s $(KUBECTL_SETVERSION)' -trimpath -buildvcs=false BUILDFLAGS_TBOT = $(ADDFLAGS) -ldflags '-w -s $(KUBECTL_SETVERSION)' -trimpath -buildvcs=false BUILDFLAGS_TELEPORT_UPDATE = $(ADDFLAGS) -ldflags '-w -s $(KUBECTL_SETVERSION)' -trimpath -buildvcs=false endif ifeq ("$(OS)","darwin") # Set the minimum version for macOS builds for Go, Rust and Xcode builds. # (as of Go 1.25 we require macOS 12) MINIMUM_SUPPORTED_MACOS_VERSION = 12.0 MACOSX_VERSION_MIN_FLAG = -mmacosx-version-min=$(MINIMUM_SUPPORTED_MACOS_VERSION) # Go CGOFLAG = CGO_ENABLED=1 CGO_CFLAGS=$(MACOSX_VERSION_MIN_FLAG) # Xcode and rust and Go linking MACOSX_DEPLOYMENT_TARGET = $(MINIMUM_SUPPORTED_MACOS_VERSION) export MACOSX_DEPLOYMENT_TARGET endif CGOFLAG_TSH ?= $(CGOFLAG) # Map ARCH into the architecture flag for electron-builder if they # are different to the Go $(ARCH) we use as an input. ELECTRON_BUILDER_ARCH_amd64 = x64 ELECTRON_BUILDER_ARCH = $(or $(ELECTRON_BUILDER_ARCH_$(ARCH)),$(ARCH)) # # 'make all' builds all 4 executables and places them in the current directory. # # NOTE: Works the same as `make`. Left for legacy reasons. .PHONY: all all: version @echo "---> Building OSS binaries." $(MAKE) $(BINARIES) # # make binaries builds all binaries defined in the BINARIES environment variable # .PHONY: binaries binaries: $(BINARIES) # Appending new conditional settings for community build type for tools. ifeq ("$(GITHUB_REPOSITORY_OWNER)","gravitational") # TELEPORT_LDFLAGS and TOOLS_LDFLAGS if appended will overwrite the previous LDFLAGS set in the BUILDFLAGS. # This is done here to prevent any changes to the (BUI)LDFLAGS passed to the other binaries TELEPORT_LDFLAGS ?= -ldflags '$(GO_LDFLAGS) -X github.com/gravitational/teleport/lib/modules.teleportBuildType=community' TOOLS_LDFLAGS ?= -ldflags '$(GO_LDFLAGS) $(KUBECTL_SETVERSION) -X github.com/gravitational/teleport/lib/modules.teleportBuildType=community' endif # By making these 3 targets below (tsh, tctl and teleport) PHONY we are solving # several problems: # * Build will rely on go build internal caching https://golang.org/doc/go1.10 at all times # * Manual change detection was broken on a large dependency tree # If you are considering changing this behavior, please consult with dev team first # # NOTE: Any changes to the `tctl` build here must be copied to `build.assets/windows/build.ps1` # until we can use this Makefile for native Windows builds. .PHONY: $(BUILDDIR)/tctl $(BUILDDIR)/tctl: @if [[ "$(OS)" != "windows" && -z "$(LIBFIDO2_BUILD_TAG)" ]]; then \ echo 'Warning: Building tctl without libfido2. Install libfido2 to have access to MFA.' >&2; \ fi GOOS=$(OS) GOARCH=$(ARCH) $(CGOFLAG) go build -tags "grpcnotrace $(PAM_TAG) $(FIPS_TAG) $(LIBFIDO2_BUILD_TAG) $(TOUCHID_TAG) $(PIV_BUILD_TAG) $(KUSTOMIZE_NO_DYNAMIC_PLUGIN)" -o $(BUILDDIR)/tctl $(BUILDFLAGS) $(TOOLS_LDFLAGS) ./tool/tctl .PHONY: $(BUILDDIR)/teleport $(BUILDDIR)/teleport: ensure-webassets rdpclient session/reexec/embed/sessionhelper GOOS=$(OS) GOARCH=$(ARCH) $(CGOFLAG) go build -tags "grpcnotrace webassets_embed $(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(SESSIONHELPER_EMBED_TAG) $(WEBASSETS_TAG) $(RDPCLIENT_TAG) $(PIV_BUILD_TAG) $(KUSTOMIZE_NO_DYNAMIC_PLUGIN)" -o $(BUILDDIR)/teleport $(BUILDFLAGS) $(TELEPORT_LDFLAGS) ./tool/teleport .PHONY: $(BUILDDIR)/sessionhelper $(BUILDDIR)/sessionhelper: ifneq ($(SESSIONHELPER_EMBED_TAG),) GOOS=$(OS) GOARCH=$(ARCH) $(CGOFLAG) go -C session build -buildvcs=false -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) gravitational_trace.nocrypto" -o '$(abspath $(BUILDDIR)/sessionhelper)' $(BUILDFLAGS) ./cmd/sessionhelper endif .PHONY: session/reexec/embed/sessionhelper session/reexec/embed/sessionhelper: $(BUILDDIR)/sessionhelper ifneq ($(SESSIONHELPER_EMBED_TAG),) mkdir -p session/reexec/embed gzip -9 -n < '$(BUILDDIR)/sessionhelper' > 'session/reexec/embed/sessionhelper_$(OS)_$(ARCH).gz' endif # NOTE: Any changes to the `tsh` build here must be copied to `build.assets/windows/build.ps1` # until we can use this Makefile for native Windows builds. .PHONY: $(BUILDDIR)/tsh $(BUILDDIR)/tsh: rdpdecoder @if [[ "$(OS)" != "windows" && -z "$(LIBFIDO2_BUILD_TAG)" ]]; then \ echo 'Warning: Building tsh without libfido2. Install libfido2 to have access to MFA.' >&2; \ fi GOOS=$(OS) GOARCH=$(ARCH) $(CGOFLAG_TSH) go build -tags "grpcnotrace $(FIPS_TAG) $(LIBFIDO2_BUILD_TAG) $(TOUCHID_TAG) $(PIV_BUILD_TAG) $(VNETDAEMON_TAG) $(TSH_RDP_DECODER_TAG) $(KUSTOMIZE_NO_DYNAMIC_PLUGIN)" -o $(BUILDDIR)/tsh $(BUILDFLAGS) $(TOOLS_LDFLAGS) ./tool/tsh .PHONY: $(BUILDDIR)/tbot # tbot is CGO-less by default except on Windows because lib/client/terminal/ wants CGO on this OS # We force cgo to be disabled, else the compiler might decide to enable it. $(BUILDDIR)/tbot: TBOT_CGO_FLAGS ?= $(if $(filter windows,$(OS)),$(CGOFLAG),CGO_ENABLED=0) $(BUILDDIR)/tbot: GOOS=$(OS) GOARCH=$(ARCH) $(TBOT_CGO_FLAGS) go build -tags "grpcnotrace $(FIPS_TAG) $(KUSTOMIZE_NO_DYNAMIC_PLUGIN)" -o $(BUILDDIR)/tbot $(BUILDFLAGS_TBOT) $(TOOLS_LDFLAGS) ./tool/tbot .PHONY: $(BUILDDIR)/teleport-update $(BUILDDIR)/teleport-update: GOOS=$(OS) GOARCH=$(ARCH) CGO_ENABLED=0 go build -tags "grpcnotrace $(FIPS_TAG)" -o $(BUILDDIR)/teleport-update $(BUILDFLAGS_TELEPORT_UPDATE) $(TOOLS_LDFLAGS) ./tool/teleport-update TELEPORT_ARGS ?= start .PHONY: teleport-hot-reload teleport-hot-reload: CompileDaemon \ --graceful-kill=true \ --exclude-dir=".git" \ --exclude-dir="build" \ --exclude-dir="e/build" \ --exclude-dir="e/web/*/node_modules" \ --exclude-dir="node_modules" \ --exclude-dir="target" \ --exclude-dir="web/packages/*/node_modules" \ --color \ --log-prefix=false \ --build="make $(BUILDDIR)/teleport" \ --command="$(BUILDDIR)/teleport $(TELEPORT_ARGS)" .PHONY: $(BUILDDIR)/fdpass-teleport $(BUILDDIR)/fdpass-teleport: cd tool/fdpass-teleport && cargo build --release --locked $(CARGO_TARGET) install tool/fdpass-teleport/target/$(RUST_TARGET_ARCH)/release/fdpass-teleport $(BUILDDIR)/ .PHONY: tsh-app tsh-app: TSH_APP_BUNDLE = $(BUILDDIR)/tsh.app tsh-app: TSH_APP_ENTITLEMENTS = build.assets/macos/$(TSH_SKELETON)/$(TSH_SKELETON).entitlements tsh-app: cp -rf "build.assets/macos/$(TSH_SKELETON)/tsh.app/" "$(TSH_APP_BUNDLE)/" mkdir -p "$(TSH_APP_BUNDLE)/Contents/MacOS/" cp "$(BUILDDIR)/tsh" "$(TSH_APP_BUNDLE)/Contents/MacOS/." $(NOTARIZE_TSH_APP) .PHONY: tctl-app tctl-app: TCTL_APP_BUNDLE = $(BUILDDIR)/tctl.app tctl-app: TCTL_APP_ENTITLEMENTS = build.assets/macos/$(TCTL_SKELETON)/$(TCTL_SKELETON).entitlements tctl-app: cp -rf "build.assets/macos/$(TCTL_SKELETON)/tctl.app/" "$(TCTL_APP_BUNDLE)/" mkdir -p "$(TCTL_APP_BUNDLE)/Contents/MacOS/" cp "$(BUILDDIR)/tctl" "$(TCTL_APP_BUNDLE)/Contents/MacOS/." $(NOTARIZE_TCTL_APP) # BPF tests will not work in a docker container and so should not be # run in CI for now. .PHONY: test-bpf test-bpf: mkdir -p _test gcc ./lib/srv/testdata/bpf_rodata_args.c -o _test/bpf_rodata_args go test -c -tags bpf,pam -o _test/libsrv.test ./lib/srv # ignore non bpf-related tests sudo TELEPORT_BPF_TEST=1 _test/libsrv.test -test.run=TestBPF # BPF support (IF ENABLED) # Requires clang 14+ # # Enable target only if /usr/include/linux/bpf.h exists and clang is installed. # This is a requirement for building BPF bytecode. .PHONY: bpf-bytecode bpf-bytecode: @if [ ! -f /usr/include/linux/bpf.h -o ! -f /usr/include/bpf/bpf_helpers.h ]; then \ echo "libbpf-dev is required to build BPF bytecode"; \ exit 1; \ fi @if ! command clang --version >/dev/null 2>&1; then \ echo "clang is required to build BPF bytecode"; \ exit 1; \ fi go generate ./lib/bpf/ # bpf-up-to-date checks if the generated BPF bytecode is up to date. .PHONY: bpf-up-to-date bpf-up-to-date: must-start-clean/host bpf-bytecode @if ! git diff --quiet; then \ ./build.assets/please-run.sh "bpf bytecode" "make -C build.assets bpf-bytecode"; \ exit 1; \ fi # Generate vmlinux.h based on the installed kernel .PHONY: update-vmlinux-h update-vmlinux-h: bpftool btf dump file /sys/kernel/btf/vmlinux format c >bpf/vmlinux.h RDPCLIENT_SKIP_CARGO ?= 0 .PHONY: rdpclient rdpclient: rustup-toolchain-warning ifeq ("$(with_rdpclient)", "yes") ifneq ($(RDPCLIENT_SKIP_CARGO),1) $(RDPCLIENT_ENV) \ cargo build -p rdp-client $(if $(FIPS),--features=fips) --release --locked $(CARGO_TARGET) else @echo "Skipping rdp-client cargo build (RDPCLIENT_SKIP_CARGO=1)" endif endif .PHONY: rdpdecoder rdpdecoder: rustup-toolchain-warning ifeq ("$(with_rdpclient)", "yes") $(RDPCLIENT_ENV) \ cargo build -p rdp-decoder --release --locked $(CARGO_TARGET) endif define ironrdp_package_json { "name": "ironrdp", "version": "0.1.0", "module": "ironrdp.js", "types": "ironrdp.d.ts", "files": ["ironrdp_bg.wasm","ironrdp.js","ironrdp.d.ts"], "sideEffects": ["./snippets/*"] } endef export ironrdp_package_json IRONRDP_SKIP_BUILD ?= 0 .PHONY: build-ironrdp-wasm build-ironrdp-wasm: ironrdp = web/packages/shared/libs/ironrdp ifeq ($(IRONRDP_SKIP_BUILD),1) build-ironrdp-wasm: @echo "Skipping ironrdp WASM build (IRONRDP_SKIP_BUILD=1)" else build-ironrdp-wasm: ensure-wasm-deps RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo build --package ironrdp --lib --target $(CARGO_WASM_TARGET) --release wasm-opt target/$(CARGO_WASM_TARGET)/release/ironrdp.wasm -o target/$(CARGO_WASM_TARGET)/release/ironrdp.wasm -O wasm-bindgen target/$(CARGO_WASM_TARGET)/release/ironrdp.wasm --out-dir $(ironrdp)/pkg --typescript --target web printenv ironrdp_package_json > $(ironrdp)/pkg/package.json endif # Build libfido2 and dependencies for MacOS. Uses exported C_ARCH variable defined earlier. .PHONY: build-fido2 build-fido2: ./build.assets/build-fido2-macos.sh build .PHONY: print-fido2-pkg-path print-fido2-pkg-path: @./build.assets/build-fido2-macos.sh pkg_config_path # # make full - Builds Teleport binaries with the built-in web assets and # places them into $(BUILDDIR). On Windows, this target is skipped because # only tsh and tctl are built. # .PHONY:full full: WEBASSETS_SKIP_BUILD = 0 full: ensure-webassets ifneq ("$(OS)", "windows") export WEBASSETS_SKIP_BUILD=0 $(MAKE) all endif # # make full-ent - Builds Teleport enterprise binaries # .PHONY: full-ent full-ent: ensure-webassets-e ifneq ("$(OS)", "windows") @if [ -f e/Makefile ]; then $(MAKE) -C e full; fi endif # # make clean - Removes all build artifacts. # .PHONY: clean clean: clean-ui clean-build .PHONY: clean-build clean-build: @echo "---> Cleaning up OSS build artifacts." rm -rf $(BUILDDIR) rm -rf ./session/reexec/embed -cargo clean -go clean -cache rm -f *.gz rm -f *.zip rm -f gitref.go rm -rf build.assets/tooling/bin # Clean up wasm build artifacts rm -rf web/packages/shared/libs/ironrdp/pkg/ .PHONY: clean-ui clean-ui: rm -rf webassets/* rm -rf build.assets/.cache/ts rm -rf web/packages/teleterm/build find . -type d -name node_modules -prune -exec rm -rf {} \; .PHONY: clean-ent clean-ent: $(MAKE) -C e clean # RELEASE_DIR is where release artifact files are put, such as tarballs, packages, etc. $(RELEASE_DIR): mkdir -p $@ # # make release - Produces a binary release tarball. # .PHONY: release release: @echo "---> OSS $(RELEASE_MESSAGE)" ifeq ("$(OS)", "windows") $(MAKE) --no-print-directory release-windows else ifeq ("$(OS)", "darwin") $(MAKE) --no-print-directory release-darwin else $(MAKE) --no-print-directory release-unix endif .PHONY: release-ent release-ent: $(MAKE) -C e release # These are aliases used to make build commands uniform. .PHONY: release-amd64 release-amd64: $(MAKE) release ARCH=amd64 .PHONY: release-386 release-386: $(MAKE) release ARCH=386 .PHONY: release-arm release-arm: $(MAKE) release ARCH=arm .PHONY: release-arm64 release-arm64: $(MAKE) release ARCH=arm64 # # make build-archive - Packages the results of a build into a release tarball # .PHONY: build-archive ifeq ("$(OS)","darwin") build-archive: INSTALL_SCRIPT=build.assets/macos/install else build-archive: INSTALL_SCRIPT=build.assets/install endif build-archive: | $(RELEASE_DIR) @echo "---> Creating OSS release archive." mkdir teleport cp -rf $(BINARIES) \ examples \ "$(INSTALL_SCRIPT)" \ README.md \ CHANGELOG.md \ build.assets/LICENSE-community \ teleport/ # add SELinux install script for Linux archives $(if $(filter linux,$(OS)), \ cp assets/install-scripts/install-selinux.sh teleport/ \ ) echo $(GITTAG) > teleport/VERSION tar $(TAR_FLAGS) -c teleport | gzip -n > $(RELEASE).tar.gz cp $(RELEASE).tar.gz $(RELEASE_DIR) # linux-amd64 generates a centos7-compatible archive. Make a copy with the -centos7 label, # for the releases page. We should probably drop that at some point. $(if $(filter linux-amd64,$(OS)-$(ARCH)), \ cp $(RELEASE).tar.gz $(RELEASE_DIR)/$(subst amd64,amd64-centos7,$(RELEASE)).tar.gz \ ) rm -rf teleport @echo "---> Created $(RELEASE).tar.gz." .PHONY: build-update-archive build-update-archive: | $(RELEASE_DIR) @echo "---> Creating OSS update release archive." mkdir -p teleport cp -rf $(UPDATE_BINARIES) \ CHANGELOG.md \ build.assets/LICENSE-community \ teleport/ echo $(GITTAG) > teleport/VERSION tar $(TAR_FLAGS) -c teleport | gzip -n > $(RELEASE_UPDATE).tar.gz cp $(RELEASE_UPDATE).tar.gz $(RELEASE_DIR) # linux-amd64 generates a centos7-compatible archive. Make a copy with the -centos7 label, # for the releases page. We should probably drop that at some point. $(if $(filter linux-amd64,$(OS)-$(ARCH)), \ cp $(RELEASE_UPDATE).tar.gz $(RELEASE_DIR)/$(subst amd64,amd64-centos7,$(RELEASE_UPDATE)).tar.gz \ ) rm -rf teleport @echo "---> Created $(RELEASE_UPDATE).tar.gz." # # make release-unix - Produces binary release tarballs for both OSS and # Enterprise editions, containing teleport, tctl, tbot and tsh. # .PHONY: release-unix release-unix: clean full build-archive build-update-archive @if [ -f e/Makefile ]; then $(MAKE) -C e release; fi # release-unix-preserving-webassets cleans just the build and not the UI # allowing webassets to be built in a prior step before building the release. .PHONY: release-unix-preserving-webassets release-unix-preserving-webassets: clean-build full build-archive build-update-archive @if [ -f e/Makefile ]; then $(MAKE) -C e release; fi include darwin-signing.mk .PHONY: release-darwin-unsigned release-darwin-unsigned: RELEASE:=$(RELEASE)-unsigned release-darwin-unsigned: full build-archive SIGNED_BINARIES := $(BINARIES:%tsh=%tsh.app) SIGNED_BINARIES := $(SIGNED_BINARIES:%tctl=%tctl.app) .PHONY: release-darwin ifneq ($(ARCH),universal) release-darwin: release-darwin-unsigned $(NOTARIZE_BINARIES) $(MAKE) tsh-app tctl-app $(MAKE) build-archive BINARIES="$(SIGNED_BINARIES)" @if [ -f e/Makefile ]; then $(MAKE) -C e release; fi else # release-darwin for ARCH == universal does not build binaries, but instead # combines previously-built binaries. For this, it depends on the ARM64 and # AMD64 signed tarballs being built into $(RELEASE_DIR). The dependencies # expressed here will not make that happen as this is typically done on CI # where these two tarballs are built in separate pipelines, and copied in for # the universal build. # # For local manual runs, create these tarballs with: # make ARCH=arm64 release-darwin # make ARCH=amd64 release-darwin # Ensure you have the rust toolchains for these installed by running # make ARCH=arm64 rustup-install-target-toolchain # make ARCH=amd64 rustup-install-target-toolchain release-darwin: TARBINS := $(TARBINS:%tsh=%tsh.app) release-darwin: TARBINS := $(TARBINS:%tctl=%tctl.app) release-darwin: $(RELEASE_darwin_arm64) $(RELEASE_darwin_amd64) mkdir -p $(BUILDDIR_arm64) $(BUILDDIR_amd64) tar -C $(BUILDDIR_arm64) -xzf $(RELEASE_darwin_arm64) --strip-components=1 $(TARBINS) tar -C $(BUILDDIR_amd64) -xzf $(RELEASE_darwin_amd64) --strip-components=1 $(TARBINS) lipo -create -output $(BUILDDIR)/teleport $(BUILDDIR_arm64)/teleport $(BUILDDIR_amd64)/teleport lipo -create -output $(BUILDDIR)/tbot $(BUILDDIR_arm64)/tbot $(BUILDDIR_amd64)/tbot lipo -create -output $(BUILDDIR)/fdpass-teleport $(BUILDDIR_arm64)/fdpass-teleport $(BUILDDIR_amd64)/fdpass-teleport lipo -create -output $(BUILDDIR)/tsh \ $(BUILDDIR_arm64)/tsh.app/Contents/MacOS/tsh \ $(BUILDDIR_amd64)/tsh.app/Contents/MacOS/tsh lipo -create -output $(BUILDDIR)/tctl \ $(BUILDDIR_arm64)/tctl.app/Contents/MacOS/tctl \ $(BUILDDIR_amd64)/tctl.app/Contents/MacOS/tctl $(NOTARIZE_BINARIES) $(MAKE) tsh-app tctl-app $(MAKE) ARCH=universal build-archive BINARIES="$(SIGNED_BINARIES)" @if [ -f e/Makefile ]; then $(MAKE) -C e release; fi endif # # make release-windows-unsigned - Produces a binary release archive containing tsh and tctl. # .PHONY: release-windows-unsigned release-windows-unsigned: clean all @echo "---> Creating OSS release archive." mkdir teleport cp -rf $(BUILDDIR)/* \ README.md \ CHANGELOG.md \ teleport/ mv teleport/tsh teleport/tsh-unsigned.exe mv teleport/tctl teleport/tctl-unsigned.exe echo $(GITTAG) > teleport/VERSION zip -9 -y -r -q $(RELEASE)-unsigned.zip teleport/ rm -rf teleport/ @echo "---> Created $(RELEASE)-unsigned.zip." # # make release-windows - Produces an archive containing a signed release of # tsh.exe and tctl.exe # .PHONY: release-windows release-windows: release-windows-unsigned @if [ ! -f "windows-signing-cert.pfx" ]; then \ echo "windows-signing-cert.pfx is missing or invalid, cannot create signed archive."; \ exit 1; \ fi rm -rf teleport @echo "---> Extracting $(RELEASE)-unsigned.zip" unzip $(RELEASE)-unsigned.zip @echo "---> Signing Windows tsh binary." @osslsigncode sign \ -pkcs12 "windows-signing-cert.pfx" \ -n "Teleport" \ -i https://goteleport.com \ -t http://timestamp.digicert.com \ -h sha2 \ -in teleport/tsh-unsigned.exe \ -out teleport/tsh.exe; \ success=$$?; \ rm -f teleport/tsh-unsigned.exe; \ if [ "$${success}" -ne 0 ]; then \ echo "Failed to sign tsh.exe, aborting."; \ exit 1; \ fi echo "---> Signing Windows tctl binary." @osslsigncode sign \ -pkcs12 "windows-signing-cert.pfx" \ -n "Teleport" \ -i https://goteleport.com \ -t http://timestamp.digicert.com \ -h sha2 \ -in teleport/tctl-unsigned.exe \ -out teleport/tctl.exe; \ success=$$?; \ rm -f teleport/tctl-unsigned.exe; \ if [ "$${success}" -ne 0 ]; then \ echo "Failed to sign tctl.exe, aborting."; \ exit 1; \ fi zip -9 -y -r -q $(RELEASE).zip teleport/ rm -rf teleport/ @echo "---> Created $(RELEASE).zip." # # make release-connect produces a release package of Teleport Connect. # It is used only for MacOS releases. Windows releases do not use this # Makefile. Linux uses the `teleterm` target in build.assets/Makefile. # # Either CONNECT_TSH_BIN_PATH or CONNECT_TSH_APP_PATH environment variable # should be defined for the `pnpm package-term` command to succeed. CI sets # this appropriately depending on whether a push build is running, or a # proper release (a proper release needs the APP_PATH as that points to # the complete signed package). See web/packages/teleterm/README.md for # details. .PHONY: release-connect release-connect: | $(RELEASE_DIR) pnpm install --frozen-lockfile pnpm build-term pnpm package-term -c.extraMetadata.version=$(VERSION) --$(ELECTRON_BUILDER_ARCH) # Only copy proper builds with tsh.app to $(RELEASE_DIR) # Drop -universal "arch" from dmg and zip name when copying to $(RELEASE_DIR) if [ -n "$$CONNECT_TSH_APP_PATH" ]; then \ DMG_TARGET_NAME="Teleport Connect-$(VERSION)-$(ARCH).dmg"; \ ZIP_TARGET_NAME="Teleport Connect-$(VERSION)-$(ARCH)-mac.zip"; \ if [ "$(ARCH)" = 'universal' ]; then \ DMG_TARGET_NAME="$${DMG_TARGET_NAME/-universal/}"; \ ZIP_TARGET_NAME="$${ZIP_TARGET_NAME/-universal/}"; \ fi; \ cp web/packages/teleterm/build/release/"Teleport Connect-$(VERSION)-$(ELECTRON_BUILDER_ARCH).dmg" "$(RELEASE_DIR)/$${DMG_TARGET_NAME}"; \ cp web/packages/teleterm/build/release/"Teleport Connect-$(VERSION)-$(ELECTRON_BUILDER_ARCH)-mac.zip" "$(RELEASE_DIR)/$${ZIP_TARGET_NAME}"; \ fi # # Remove trailing whitespace in all markdown files under docs/. # # Note: this runs in a busybox container to avoid incompatibilities between # linux and macos CLI tools. # .PHONY: docs-fix-whitespace docs-fix-whitespace: docker run --rm -v $(PWD):/teleport busybox \ find /teleport/docs/ -type f -name '*.md' -exec sed -E -i 's/\s+$$//g' '{}' \; # # Test docs for trailing whitespace and broken links # .PHONY: docs-test docs-test: docs-test-whitespace # # Check for trailing whitespace in all markdown files under docs/ # .PHONY: docs-test-whitespace docs-test-whitespace: if find docs/ -type f -name '*.md' | xargs grep -E '\s+$$'; then \ echo "trailing whitespace found in docs/ (see above)"; \ echo "run 'make docs-fix-whitespace' to fix it"; \ exit 1; \ fi # # Builds some tooling for filtering and displaying test progress/output/etc # # Deprecated: Use gotestsum instead. TOOLINGDIR := ${abspath ./build.assets/tooling} RENDER_TESTS := $(TOOLINGDIR)/bin/render-tests $(RENDER_TESTS): $(wildcard $(TOOLINGDIR)/cmd/render-tests/*.go) cd $(TOOLINGDIR) && go build -o "$@" ./cmd/render-tests DIFF_TEST := $(TOOLINGDIR)/bin/difftest $(DIFF_TEST): $(wildcard $(TOOLINGDIR)/cmd/difftest/*.go) cd $(TOOLINGDIR) && go build -o "$@" ./cmd/difftest BENCHFIND := $(TOOLINGDIR)/bin/benchfind $(BENCHFIND): $(wildcard $(TOOLINGDIR)/cmd/benchfind/*.go) cd $(TOOLINGDIR) && go build -o "$@" ./cmd/benchfind RERUN := $(TOOLINGDIR)/bin/rerun $(RERUN): $(wildcard $(TOOLINGDIR)/cmd/rerun/*.go) cd $(TOOLINGDIR) && go build -o "$@" ./cmd/rerun # # Runs all Go/shell tests, called by CI/CD. # .PHONY: test test: test-helm test-sh test-api test-go test-rust test-operator test-terraform-provider $(TEST_LOG_DIR): mkdir -p $(TEST_LOG_DIR) .PHONY: helmunit/installed helmunit/installed: @if ! helm unittest -h >/dev/null; then \ echo 'Helm unittest plugin is required to test Helm charts. Run `helm plugin install https://github.com/quintush/helm-unittest --version 0.2.11` to install it'; \ exit 1; \ fi # The CI environment is responsible for setting HELM_PLUGINS to a directory where # quintish/helm-unittest is installed. # # Github Actions build uses /workspace as homedir and Helm can't pick up plugins by default there, # so override the plugin location via environemnt variable when running in CI. Github Actions provide CI=true # environment variable. .PHONY: test-helm test-helm: helmunit/installed $(HELMJANITOR) test .PHONY: test-helm-update-snapshots test-helm-update-snapshots: helmunit/installed $(HELMJANITOR) test --update-snapshots # # Runs all Go tests except integration, called by CI/CD. # .PHONY: test-go test-go: test-go-unit test-go-touch-id test-go-vnet-daemon test-go-tsh test-go-chaos # # Runs a test to ensure no environment variable leak into build binaries. # This is typically done as part of the bloat test in CI, but this # target exists for local testing. # .PHONY: test-env-leakage test-env-leakage: $(eval export BUILD_SECRET=FAKE_SECRET) $(MAKE) full failed=0; \ for binary in $(BINARIES); do \ if strings $$binary | grep -q 'FAKE_SECRET'; then \ echo "Error: $$binary contains FAKE_SECRET"; \ failed=1; \ fi; \ done; \ if [ $$failed -eq 1 ]; then \ echo "Environment leak failure"; \ exit 1; \ else \ echo "No environment leak, PASS"; \ fi # Runs test prepare steps .PHONY: test-go-prepare test-go-prepare: ensure-webassets rdpclient $(VERSRC) | $(TEST_LOG_DIR) # Runs base unit tests .PHONY: test-go-unit test-go-unit: rdpclient test-go-unit: FLAGS ?= -race -shuffle on test-go-unit: SUBJECT ?= $(shell go list ./... | grep -vE 'teleport/(e2e|integration|tool/tsh|integrations/operator|integrations/access|integrations/lib)') test-go-unit: test-go-prepare | $(TEST_LOG_DIR) $(CGOFLAG) go test -json -tags "$(PAM_TAG) $(RDPCLIENT_TAG) $(FIPS_TAG) $(BPF_TAG) $(LIBFIDO2_TEST_TAG) $(TOUCHID_TAG) $(PIV_TEST_TAG) $(VNETDAEMON_TAG) $(ADDTAGS)" $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests.xml --jsonfile $(TEST_LOG_DIR)/unit-tests.json --raw-command -- cat # Runs tbot unit tests .PHONY: test-go-unit-tbot test-go-unit-tbot: FLAGS ?= -race -shuffle on test-go-unit-tbot: | $(TEST_LOG_DIR) $(CGOFLAG) go test -json $(FLAGS) $(ADDFLAGS) ./tool/tbot/... ./lib/tbot/... \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-tbot.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-tbot.json --raw-command -- cat # Make sure untagged touchid code build/tests. .PHONY: test-go-touch-id test-go-touch-id: FLAGS ?= -race -shuffle on test-go-touch-id: SUBJECT ?= ./lib/auth/touchid/... test-go-touch-id: test-go-prepare | $(TEST_LOG_DIR) ifneq ("$(TOUCHID_TAG)", "") $(CGOFLAG) go test -json $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-touchid.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-touchid.json --raw-command -- cat endif # By default, the parameters run each benchmark only once. # This is intended to run in CI during unit testing to make sure benchmarks don't break. # To limit noise and improve speed this will only run on packages that have benchmarks. # Race detection is not enabled because it significantly slows down benchmarks. # todo: Use gotestsum when it is compatible with benchmark output. Currently will consider all benchmarks failed. .PHONY: test-go-bench test-go-bench: BENCHMARK_SKIP_PATTERN = "^BenchmarkRoot" test-go-bench: BENCH_OUTPUT ?= $(TEST_LOG_DIR)/bench.txt test-go-bench: BENCH_ARGS ?= test-go-bench: BENCH_TIME ?= "1x" test-go-bench: BENCH_COUNT ?= 1 test-go-bench: $(BENCHFIND) | $(TEST_LOG_DIR) @PKGS=$$($(BENCHFIND) --tags=$(BUILD_TAGS)) ; \ if [ -z "$$PKGS" ]; then \ echo "No benchmark packages found"; \ exit 1; \ fi ; \ go test -run ^$$ -bench . -skip $(BENCHMARK_SKIP_PATTERN) -count $(BENCH_COUNT) -benchtime $(BENCH_TIME) $(BENCH_ARGS) $$PKGS \ | tee $(BENCH_OUTPUT) .PHONY: test-go-bench-root test-go-bench-root: BENCHMARK_PATTERN = "^BenchmarkRoot" test-go-bench-root: BENCHMARK_SKIP_PATTERN = "" test-go-bench-root: BENCH_OUTPUT ?= $(TEST_LOG_DIR)/bench.txt test-go-bench-root: BENCH_ARGS ?= test-go-bench-root: BENCH_TIME ?= "1x" test-go-bench-root: BENCH_COUNT ?= 1 test-go-bench-root: $(BENCHFIND) | $(TEST_LOG_DIR) @PKGS=$$($(BENCHFIND) --tags=$(BUILD_TAGS)) ; \ if [ -z "$$PKGS" ]; then \ echo "No benchmark packages found"; \ exit 1; \ fi ; \ go test -run ^$$ -bench $(BENCHMARK_PATTERN) -skip $(BENCHMARK_SKIP_PATTERN) -count $(BENCH_COUNT) -benchtime $(BENCH_TIME) $(BENCH_ARGS) $$PKGS \ | tee $(BENCH_OUTPUT) # Make sure untagged vnetdaemon code build/tests. .PHONY: test-go-vnet-daemon test-go-vnet-daemon: FLAGS ?= -race -shuffle on test-go-vnet-daemon: SUBJECT ?= ./lib/vnet/daemon/... test-go-vnet-daemon: test-go-prepare | $(TEST_LOG_DIR) ifneq ("$(VNETDAEMON_TAG)", "") $(CGOFLAG) go test -json $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-vnet.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-vnet.json --raw-command -- cat endif # Runs ci tsh tests .PHONY: test-go-tsh test-go-tsh: FLAGS ?= -race -shuffle on test-go-tsh: SUBJECT ?= github.com/gravitational/teleport/tool/tsh/... test-go-tsh: test-go-prepare | $(TEST_LOG_DIR) $(CGOFLAG_TSH) go test -json -tags "$(PAM_TAG) $(FIPS_TAG) $(LIBFIDO2_TEST_TAG) $(TOUCHID_TAG) $(PIV_TEST_TAG) $(VNETDAEMON_TAG)" $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-tsh.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-tsh.json --raw-command -- cat # Chaos tests have high concurrency, run without race detector and have TestChaos prefix. .PHONY: test-go-chaos test-go-chaos: CHAOS_FOLDERS = $(shell find . -type f -name '*chaos*.go' | xargs dirname | uniq) test-go-chaos: test-go-prepare | $(TEST_LOG_DIR) $(CGOFLAG) go test -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" -test.run=TestChaos $(CHAOS_FOLDERS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-chaos.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-chaos.json --raw-command -- cat # # Runs all Go tests except integration, end-to-end, and chaos, called by CI/CD. # UNIT_ROOT_REGEX := ^TestRoot .PHONY: test-go-root test-go-root: ensure-webassets rdpclient | $(TEST_LOG_DIR) test-go-root: FLAGS ?= -race -shuffle on test-go-root: PACKAGES = $(shell go list $(ADDFLAGS) ./... | grep -v -e e2e -e integration -e integrations/operator) test-go-root: $(VERSRC) $(CGOFLAG) go test -json -run "$(UNIT_ROOT_REGEX)" -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-root.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-root.json --raw-command -- cat # # Runs Go tests on the api module. These have to be run separately as the package name is different. # .PHONY: test-api test-api: $(VERSRC) | $(TEST_LOG_DIR) test-api: FLAGS ?= -race -shuffle on test-api: SUBJECT ?= $(shell cd api && go list ./...) test-api: cd api && $(CGOFLAG) go test -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-api.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-api.json --raw-command -- cat # # Runs Teleport Operator tests. # We have to run them using the makefile to ensure the installation of the k8s test tools (envtest) # .PHONY: test-operator test-operator: $(MAKE) -C integrations/operator test TEST_LOG_DIR=$(TEST_LOG_DIR) # # Runs Teleport Terraform provider tests. # .PHONY: test-terraform-provider test-terraform-provider: $(MAKE) -C integrations test-terraform-provider TEST_LOG_DIR=$(TEST_LOG_DIR) # # Runs Teleport MWI Terraform provider tests. # .PHONY: test-terraform-provider-mwi test-terraform-provider-mwi: $(MAKE) -C integrations test-terraform-provider-mwi TEST_LOG_DIR=$(TEST_LOG_DIR) # # Runs Go tests on the integrations/kube-agent-updater module. These have to be run separately as the package name is different. # .PHONY: test-kube-agent-updater test-kube-agent-updater: $(VERSRC) | $(TEST_LOG_DIR) test-kube-agent-updater: FLAGS ?= -race -shuffle on test-kube-agent-updater: SUBJECT ?= $(shell cd integrations/kube-agent-updater && go list ./...) test-kube-agent-updater: cd integrations/kube-agent-updater && $(CGOFLAG) go test -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-kube-agent-updater.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-kube-agent-updater.json --raw-command -- cat .PHONY: test-access-integrations test-access-integrations: $(MAKE) -C integrations test-access .PHONY: test-event-handler-integrations test-event-handler-integrations: $(MAKE) -C integrations test-event-handler .PHONY: test-integrations-lib test-integrations-lib: $(MAKE) -C integrations test-lib # # Runs Go tests on the examples/teleport-usage module. These have to be run separately as the package name is different. # .PHONY: test-teleport-usage test-teleport-usage: $(VERSRC) | $(TEST_LOG_DIR) test-teleport-usage: FLAGS ?= -race -shuffle on test-teleport-usage: SUBJECT ?= $(shell cd examples/teleport-usage && go list ./...) test-teleport-usage: cd examples/teleport-usage && $(CGOFLAG) go test -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" $(PACKAGES) $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-teleport-usage.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-teleport-usage.json --raw-command -- cat # # Flaky test detection. Usually run from CI nightly, overriding these default parameters # This runs the same tests as test-go-unit but repeatedly to try to detect flaky tests. # # TODO(jakule): Migrate to gotestsum .PHONY: test-go-flaky FLAKY_RUNS ?= 3 FLAKY_TIMEOUT ?= 1h FLAKY_TOP_N ?= 20 FLAKY_SUMMARY_FILE ?= /tmp/flaky-report.txt test-go-flaky: rdpclient test-go-flaky: FLAGS ?= -race -shuffle on test-go-flaky: SUBJECT ?= $(shell go list ./... | grep -v -e e2e -e integration -e tool/tsh -e integrations/operator -e integrations/access -e integrations/lib ) test-go-flaky: GO_BUILD_TAGS ?= $(PAM_TAG) $(FIPS_TAG) $(RDPCLIENT_TAG) $(BPF_TAG) $(TOUCHID_TAG) $(PIV_TEST_TAG) $(LIBFIDO2_TEST_TAG) $(VNETDAEMON_TAG) test-go-flaky: RENDER_FLAGS ?= -report-by flakiness -summary-file $(FLAKY_SUMMARY_FILE) -top $(FLAKY_TOP_N) test-go-flaky: test-go-prepare $(RENDER_TESTS) $(RERUN) $(CGOFLAG) $(RERUN) -n $(FLAKY_RUNS) -t $(FLAKY_TIMEOUT) \ go test -count=1 -json -tags "$(GO_BUILD_TAGS)" $(SUBJECT) $(FLAGS) $(ADDFLAGS) \ | $(RENDER_TESTS) $(RENDER_FLAGS) # # Runs cargo test on our Rust modules. # (a no-op if cargo and rustc are not installed) # ifneq ($(CHECK_RUST),) ifneq ($(CHECK_CARGO),) .PHONY: test-rust test-rust: cargo test else .PHONY: test-rust test-rust: endif endif # Run all shell script unit tests (using https://github.com/bats-core/bats-core) .PHONY: test-sh test-sh: @if ! type bats 2>&1 >/dev/null; then \ echo "Not running 'test-sh' target as 'bats' is not installed."; \ if [ "$${CI}" = "true" ]; then echo "This is a failure when running in CI." && exit 1; fi; \ exit 0; \ fi; \ bats $(BATSFLAGS) ./assets/aws/files/tests .PHONY: run-etcd run-etcd: docker build -f .github/services/Dockerfile.etcd -t etcdbox --build-arg=ETCD_VERSION=3.5.9 . docker run -it --rm -p'2379:2379' etcdbox # # Integration tests. Need a TTY to work. # Any tests which need to run as root must be skipped during regular integration testing. # .PHONY: integration integration: FLAGS ?= -v -race integration: PACKAGES = $(shell go list ./... | grep 'integration\([^s]\|$$\)' | grep -v integrations/lib/testing/integration ) integration: session/reexec/embed/sessionhelper | $(TEST_LOG_DIR) @echo KUBECONFIG is: $(KUBECONFIG), TEST_KUBE: $(TEST_KUBE) $(CGOFLAG) go test -timeout 30m -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(SESSIONHELPER_EMBED_TAG)" $(PACKAGES) $(FLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-integration.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-integration.json --raw-command -- cat # # Integration tests that run Kubernetes tests in order to complete successfully # are run separately to all other integration tests. # INTEGRATION_KUBE_REGEX := TestKube.* .PHONY: integration-kube integration-kube: FLAGS ?= -v -race integration-kube: PACKAGES = $(shell go list ./... | grep 'integration\([^s]\|$$\)' | grep -v 'integration/autoupdate') integration-kube: | $(TEST_LOG_DIR) @echo KUBECONFIG is: $(KUBECONFIG), TEST_KUBE: $(TEST_KUBE) $(CGOFLAG) go test -json -run "$(INTEGRATION_KUBE_REGEX)" $(PACKAGES) $(FLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-integration-kube.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-integration-kube.json --raw-command -- cat # # Integration tests which need to be run as root in order to complete successfully # are run separately to all other integration tests. Need a TTY to work. # INTEGRATION_ROOT_REGEX := ^TestRoot .PHONY: integration-root integration-root: FLAGS ?= -v -race integration-root: PACKAGES = $(shell go list ./... | grep 'integration\([^s]\|$$\)') integration-root: session/reexec/embed/sessionhelper | $(TEST_LOG_DIR) $(CGOFLAG) go test -json -tags '$(SESSIONHELPER_EMBED_TAG)' -run "$(INTEGRATION_ROOT_REGEX)" $(PACKAGES) $(FLAGS) \ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-integration-root.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-integration-root.json --raw-command -- cat .PHONY: e2e-aws e2e-aws: FLAGS ?= -v -race e2e-aws: PACKAGES = $(shell go list ./... | grep 'e2e/aws') e2e-aws: | $(TEST_LOG_DIR) @echo TEST_KUBE: $(TEST_KUBE) TEST_AWS_DB: $(TEST_AWS_DB) $(CGOFLAG) go test -json $(PACKAGES) $(FLAGS) $(ADDFLAGS)\ | $(GOTESTSUM) --junitfile $(TEST_LOG_DIR)/unit-tests-e2e-aws.xml --jsonfile $(TEST_LOG_DIR)/unit-tests-e2e-aws.json --raw-command -- cat # e2e-binaries builds teleport, tctl, and tsh (with webauthnmock) in parallel # for use in e2e tests. .PHONY: e2e-binaries e2e-binaries: build.assets/build-e2e-binaries.sh # # Lint the source code. # By default lint scans the entire repo. Pass GO_LINT_FLAGS='--new' to only scan local # changes (or last commit). # .PHONY: lint lint: lint-api lint-go lint-kube-agent-updater lint-tools lint-protos lint-no-actions # # Runs linters without dedicated GitHub Actions. # .PHONY: lint-no-actions lint-no-actions: lint-sh lint-license .PHONY: lint-tools lint-tools: lint-build-tooling lint-backport # # Checks that testing symbols and the testify library is not included in binaries. # # .PHONY: lint-test-symbols lint-test-symbols: @testing_count=`$(GODA) tree "reach(github.com/gravitational/teleport/tool/...:all, testing)" | tee /dev/stderr | wc -l | tr -d ' '`; \ if [ "$$testing_count" -gt 0 ]; then \ echo ""; \ echo "FAIL: \"testing\" is included in binaries"; \ fi; \ testify_count=`$(GODA) tree "reach(github.com/gravitational/teleport/tool/...:all, github.com/stretchr/testify/...)" | tee /dev/stderr | wc -l | tr -d ' '`; \ if [ "$$testify_count" -gt 0 ]; then \ echo ""; \ echo "FAIL: \"github.com/stretchr/testify\" is included in binaries"; \ fi; \ if [ "$$testing_count" -gt 0 ] || [ "$$testify_count" -gt 0 ]; then \ exit 1; \ fi # # Runs the clippy linter and rustfmt on our rust modules # (a no-op if cargo and rustc are not installed) # ifneq ($(CHECK_RUST),) ifneq ($(CHECK_CARGO),) .PHONY: lint-rust lint-rust: cargo clippy --locked --all-targets -- -D warnings \ && cargo fmt -- --check else .PHONY: lint-rust lint-rust: endif endif .PHONY: lint-go lint-go: GO_LINT_FLAGS ?= lint-go: golangci-lint run -c .golangci.yml --build-tags='$(LIBFIDO2_TEST_TAG) $(TOUCHID_TAG) $(PIV_LINT_TAG) $(VNETDAEMON_TAG)' $(GO_LINT_FLAGS) $(MAKE) -C integrations/terraform lint $(MAKE) -C integrations/event-handler lint .PHONY: fix-imports fix-imports: $(MAKE) -C build.assets fix-imports .PHONY: fix-imports/host fix-imports/host: $(GCI) write -s standard -s default -s 'prefix(github.com/gravitational/teleport)' -s 'prefix(github.com/gravitational/teleport/integrations/terraform,github.com/gravitational/teleport/integrations/event-handler)' --skip-generated . lint-build-tooling: GO_LINT_FLAGS ?= lint-build-tooling: cd build.assets/tooling && golangci-lint run -c ../../.golangci.yml $(GO_LINT_FLAGS) .PHONY: lint-backport lint-backport: GO_LINT_FLAGS ?= lint-backport: cd assets/backport && golangci-lint run -c ../../.golangci.yml $(GO_LINT_FLAGS) # api is no longer part of the teleport package, so golangci-lint skips it by default .PHONY: lint-api lint-api: GO_LINT_API_FLAGS ?= lint-api: cd api && golangci-lint run -c ../.golangci.yml --build-tags='$(PIV_LINT_TAG)' $(GO_LINT_API_FLAGS) .PHONY: lint-kube-agent-updater lint-kube-agent-updater: GO_LINT_API_FLAGS ?= lint-kube-agent-updater: cd integrations/kube-agent-updater && golangci-lint run -c ../../.golangci.yml $(GO_LINT_API_FLAGS) # TODO(awly): remove the `--exclude` flag after cleaning up existing scripts .PHONY: lint-sh lint-sh: SH_LINT_FLAGS ?= lint-sh: find . -type f \( -name '*.sh' -or -name '*.sh.tmpl' \) -not -path "*/node_modules/*" | xargs \ shellcheck \ --exclude=SC2086 \ --exclude=SC1091 \ $(SH_LINT_FLAGS) # lint AWS AMI scripts # SC1091 prints errors when "source" directives are not followed find assets/aws/files/bin -type f | xargs \ shellcheck \ --exclude=SC2086 \ --exclude=SC1091 \ --exclude=SC2129 \ $(SH_LINT_FLAGS) # Lints all the Helm charts found in directories under examples/chart and exits on failure # If there is a .lint directory inside, the chart gets linted once for each .yaml file in that directory # We inherit yamllint's 'relaxed' configuration as it's more compatible with Helm output and will only error on # show-stopping issues. Kubernetes' YAML parser is not particularly fussy. # If errors are found, the file is printed with line numbers to aid in debugging. .PHONY: lint-helm lint-helm: $(HELMJANITOR) reference -check $(HELMJANITOR) lint ADDLICENSE_COMMON_ARGS := -c 'Gravitational, Inc.' \ -ignore '**/*.c' \ -ignore '**/*.h' \ -ignore '**/*.html' \ -ignore '**/*.js' \ -ignore '**/*.py' \ -ignore '**/*.sh' \ -ignore '**/*.sql' \ -ignore '**/*.tf' \ -ignore '**/*.tftest.hcl' \ -ignore '**/*.yaml' \ -ignore '**/*.yml' \ -ignore '**/.terraform.lock.hcl' \ -ignore '**/Dockerfile' \ -ignore '**/node_modules/**' \ -ignore 'api/version.go' \ -ignore 'build.assets/.cache/**' \ -ignore 'docs/pages/includes/**/*.go' \ -ignore 'e/**' \ -ignore 'gen/**' \ -ignore 'gitref.go' \ -ignore 'lib/limiter/internal/ratelimit/**' \ -ignore 'lib/srv/desktop/rdp/decoder/target/**' \ -ignore 'lib/srv/desktop/rdp/rdpclient/target/**' \ -ignore 'lib/web/build/**' \ -ignore 'target/**' \ -ignore 'web/packages/design/src/assets/icomoon/style.css' \ -ignore 'web/packages/shared/libs/ironrdp/**' \ -ignore 'web/packages/teleterm/build/**' \ -ignore 'webassets/**' ADDLICENSE_AGPL3_ARGS := $(ADDLICENSE_COMMON_ARGS) \ -ignore 'api/**' \ -f $(CURDIR)/build.assets/LICENSE.header ADDLICENSE_APACHE2_ARGS := $(ADDLICENSE_COMMON_ARGS) \ -l apache ADDLICENSE = go run github.com/google/addlicense@v1.0.0 .PHONY: lint-license lint-license: $(ADDLICENSE) $(ADDLICENSE_AGPL3_ARGS) -check * 2>/dev/null $(ADDLICENSE) $(ADDLICENSE_APACHE2_ARGS) -check api/* 2>/dev/null .PHONY: fix-license fix-license: $(ADDLICENSE) $(ADDLICENSE_AGPL3_ARGS) * 2>/dev/null $(ADDLICENSE) $(ADDLICENSE_APACHE2_ARGS) api/* 2>/dev/null # This rule updates version files and Helm snapshots based on the Makefile # VERSION variable. # # Used prior to a release by bumping VERSION in this Makefile and then # running "make update-version". .PHONY: update-version update-version: version test-helm-update-snapshots # This rule triggers re-generation of version files if Makefile changes. .PHONY: version version: $(VERSRC) # This rule triggers re-generation of version files specified if Makefile changes. $(VERSRC) &: Makefile version.mk VERSION=$(VERSION) $(MAKE) -f version.mk setver # Pushes GITTAG and api/GITTAG to GitHub. # # Before running `make update-tag`, do: # # 1. Commit your changes # 2. Bump VERSION variable (eg, "vMAJOR.(MINOR+1).0-dev-$USER.1") # 3. Run `make update-version` # 4. Commit version changes to git # 5. Make sure it all builds (`make release` or equivalent) # 6. Run `make update-tag` to tag repos with $(VERSION) # 7. Run `make tag-build` to build the tag on GitHub Actions # 8. Run `make tag-publish` after `make tag-build` tag has completed to # publish the built artifacts. # # GHA tag builds: https://github.com/gravitational/teleport.e/actions/workflows/tag-build.yaml # GHA tag publish: https://github.com/gravitational/teleport.e/actions/workflows/tag-publish.yaml .PHONY: update-tag update-tag: TAG_REMOTE ?= origin update-tag: @test $(VERSION) cd build.assets/tooling && GOWORK=off CGO_ENABLED=0 go run ./cmd/check -check valid -tag $(GITTAG) git tag $(GITTAG) git tag api/$(GITTAG) (cd e && git tag $(GITTAG) && git push origin $(GITTAG)) git push $(TAG_REMOTE) $(GITTAG) && git push $(TAG_REMOTE) api/$(GITTAG) # find-any evaluates to non-empty (true) if any of the strings in $(1) are contained in $(2) # e.g. # $(call find-any,-cloud -dev,1.2.3-dev.1) == true # $(call find-any,-cloud -dev,1.2.3-cloud.1) == true # $(call find-any,-cloud -dev,1.2.3) == false find-any = $(strip $(foreach str,$(1),$(findstring $(str),$(2)))) # IS_CLOUD_SEMVER is non-empty if $(VERSION) contains a cloud-only pre-release tag, # and is empty if not. CLOUD_VERSIONS = -cloud. -dev.cloud. IS_CLOUD_SEMVER = $(call find-any,$(CLOUD_VERSIONS),$(VERSION)) # IS_PROD_SEMVER is non-empty if $(VERSION) does not contains a pre-release component, or # if it does, it is -cloud. PROD_VERSIONS = -cloud. IS_PROD_SEMVER = $(if $(findstring -,$(VERSION)),$(call find-any,$(PROD_VERSIONS),$(VERSION)),true) # Builds a tag build on GitHub Actions. # Starts a tag publish run using e/.github/workflows/tag-build.yaml # for the tag v$(VERSION). # If the $(VERSION) variable contains a cloud pre-release component, -cloud. or # -dev.cloud., then the tag-build workflow is run with `cloud-only=true`. This can be # specified explicitly with `make tag-build CLOUD_ONLY=`. .PHONY: tag-build tag-build: CLOUD_ONLY = $(if $(IS_CLOUD_SEMVER),true,false) tag-build: ENVIRONMENT = $(if $(IS_PROD_SEMVER),prod/build,stage/build) tag-build: @which gh >/dev/null 2>&1 || { echo 'gh command needed. https://github.com/cli/cli'; exit 1; } gh workflow run tag-build.yaml \ --repo gravitational/teleport.e \ --ref "v$(VERSION)" \ -f "oss-teleport-repo=$(shell gh repo view --json nameWithOwner --jq .nameWithOwner)" \ -f "oss-teleport-ref=v$(VERSION)" \ -f "cloud-only=$(CLOUD_ONLY)" \ -f "environment=$(ENVIRONMENT)" @echo See runs at: https://github.com/gravitational/teleport.e/actions/workflows/tag-build.yaml # Publishes a tag build. # Starts a tag publish run using e/.github/workflows/tag-publish.yaml # for the tag v$(VERSION). # If the $(VERSION) variable contains a cloud pre-release component, -cloud. or # -dev.cloud., then the tag-publish workflow is run with `cloud-only=true`. This can be # specified explicitly with `make tag-publish CLOUD_ONLY=`. .PHONY: tag-publish tag-publish: CLOUD_ONLY = $(if $(IS_CLOUD_SEMVER),true,false) tag-publish: ENVIRONMENT = $(if $(IS_PROD_SEMVER),prod/publish,stage/publish) tag-publish: @which gh >/dev/null 2>&1 || { echo 'gh command needed. https://github.com/cli/cli'; exit 1; } gh workflow run tag-publish.yaml \ --repo gravitational/teleport.e \ --ref "v$(VERSION)" \ -f "oss-teleport-repo=$(shell gh repo view --json nameWithOwner --jq .nameWithOwner)" \ -f "oss-teleport-ref=v$(VERSION)" \ -f "cloud-only=$(CLOUD_ONLY)" \ -f "environment=$(ENVIRONMENT)" @echo See runs at: https://github.com/gravitational/teleport.e/actions/workflows/tag-publish.yaml .PHONY: profile profile: go tool pprof http://localhost:6060/debug/pprof/profile .PHONY: sloccount sloccount: find . -name "*.go" -print0 | xargs -0 wc -l # # print-go-version outputs Go version as a semver without "go" prefix # .PHONY: print-go-version print-go-version: @$(MAKE) -C build.assets print-go-version | sed "s/go//" # Dockerized build: useful for making Linux releases on macOS .PHONY: docker docker: $(MAKE) -C build.assets build # Dockerized build: useful for making Linux binaries on macOS .PHONY: docker-binaries docker-binaries: clean $(MAKE) -C build.assets build-binaries PIV=$(PIV) # Interactively enters a Docker container (which you can build and run Teleport inside of) .PHONY: enter enter: $(MAKE) -C build.assets enter # Interactively enters a Docker container, as root (which you can build and run Teleport inside of) .PHONY: enter-root enter-root: $(MAKE) -C build.assets enter-root # Interactively enters a Docker container (which you can build and run Teleport inside of). # Similar to `enter`, but uses the centos7 container. .PHONY: enter/centos7 enter/centos7: $(MAKE) -C build.assets enter/centos7 .PHONY: enter/centos7-fips enter/centos7-fips: $(MAKE) -C build.assets enter/centos7-fips .PHONY: enter/grpcbox enter/grpcbox: $(MAKE) -C build.assets enter/grpcbox .PHONY:enter/node enter/node: $(MAKE) -C build.assets enter/node .PHONY: enter/arm enter/arm: $(MAKE) -C build.assets enter/arm BUF := buf # # Install buf to lint, format and generate code from protobuf files. # .PHONY: ensure-buf ensure-buf: NEED_VERSION = $(shell $(MAKE) --no-print-directory -s -C build.assets print-buf-version) ensure-buf: # Install buf if it's not already installed. ifeq (, $(shell command -v $(BUF))) go install github.com/bufbuild/buf/cmd/buf@$(NEED_VERSION) endif # protos/all runs build, lint and format on all protos. # Use `make grpc` to regenerate protos inside buildbox. .PHONY: protos/all protos/all: protos/build protos/lint protos/format .PHONY: protos/build protos/build: ensure-buf $(BUF) build .PHONY: protos/format protos/format: ensure-buf $(BUF) format -w .PHONY: protos/lint protos/lint: ensure-buf $(BUF) lint $(BUF) lint --config=buf-legacy.yaml api/proto .PHONY: protos/breaking protos/breaking: BASE=origin/master protos/breaking: ensure-buf @echo Checking compatibility against BASE=$(BASE) buf breaking . --against '.git#branch=$(BASE)' .PHONY: lint-protos lint-protos: protos/lint .PHONY: lint-breaking lint-breaking: protos/breaking GODERIVE := $(TOOLINGDIR)/bin/goderive # derive will generate derived functions for our API. # we need to build goderive first otherwise it will not be able to resolve dependencies # in the api/types/discoveryconfig package .PHONY: derive derive: cd $(TOOLINGDIR) && go build -o $(GODERIVE) ./cmd/goderive/main.go $(GODERIVE) ./api/types ./api/types/discoveryconfig ./api/types/accesslist ./api/types/userloginstate # derive-up-to-date checks if the generated derived functions are up to date. .PHONY: derive-up-to-date derive-up-to-date: must-start-clean/host derive @if ! git diff --quiet; then \ ./build.assets/please-run.sh "derived functions" "make derive"; \ exit 1; \ fi # grpc generates gRPC stubs from service definitions. # This target runs in the buildbox container. .PHONY: grpc grpc: $(MAKE) -C build.assets grpc # grpc/host generates gRPC stubs. # Unlike grpc, this target runs locally. .PHONY: grpc/host grpc/host: protos/all @build.assets/genproto.sh # protos-up-to-date checks if the generated gRPC stubs are up to date. # This target runs in the buildbox container. .PHONY: protos-up-to-date protos-up-to-date: $(MAKE) -C build.assets protos-up-to-date # protos-up-to-date/host checks if the generated gRPC stubs are up to date. # Unlike protos-up-to-date, this target runs locally. .PHONY: protos-up-to-date/host protos-up-to-date/host: must-start-clean/host grpc/host @if ! git diff --quiet; then \ ./build.assets/please-run.sh "protos gRPC" "make grpc"; \ exit 1; \ fi .PHONY: must-start-clean/host must-start-clean/host: @if ! git diff --quiet; then \ echo 'This must be run from a repo with no unstaged commits.'; \ git diff; \ exit 1; \ fi # crds-up-to-date checks if the generated CRDs from the protobuf stubs are up to date. .PHONY: crds-up-to-date crds-up-to-date: must-start-clean/host $(MAKE) -C integrations/operator crd-manifests @if ! git diff --quiet; then \ ./build.assets/please-run.sh "operator CRD manifests" "make -C integrations/operator crd"; \ exit 1; \ fi $(MAKE) -C integrations/operator crd-docs @if ! git diff --quiet; then \ ./build.assets/please-run.sh "operator CRD docs" "make -C integrations/operator crd"; \ exit 1; \ fi # tfdocs-up-to-date checks if the generated Terraform types and documentation from the protobuf stubs are up to date. .PHONY: terraform-resources-up-to-date terraform-resources-up-to-date: must-start-clean/host $(MAKE) -C integrations/terraform docs @if ! git diff --quiet; then \ ./build.assets/please-run.sh "TF provider docs" "make -C integrations/terraform docs"; \ exit 1; \ fi # terraform-module-docs-up-to-date checks if the generated Terraform module documentation is up to date. .PHONY: terraform-module-docs-up-to-date terraform-module-docs-up-to-date: must-start-clean/host $(MAKE) -C integrations/terraform-modules docs @if ! git diff --quiet; then \ ./build.assets/please-run.sh "TF module docs" "make -C integrations/terraform-modules docs"; \ exit 1; \ fi # icons-up-to-date checks if icons were pre-processed before being added to the repo. .PHONY: icons-up-to-date icons-up-to-date: must-start-clean/host pnpm process-icons @if ! git diff --quiet; then \ ./build.assets/please-run.sh "icons (see web/packages/design/src/Icon/README.md)" "pnpm process-icons"; \ exit 1; \ fi # go-generate will execute `go generate` and generate go code. .PHONY: go-generate go-generate: go generate ./lib/... # go-generate-up-to-date checks if the generated code is up to date. .PHONY: go-generate-up-to-date go-generate-up-to-date: must-start-clean/host go-generate @if ! git diff --quiet; then \ ./build.assets/please-run.sh "go generate lib" "make go-generate"; \ exit 1; \ fi .PHONY: print/env print/env: env # make install will installs system-wide teleport .PHONY: install install: build @echo "\n** Make sure to run 'make install' as root! **\n" cp -f $(BUILDDIR)/tctl $(BINDIR)/ cp -f $(BUILDDIR)/tsh $(BINDIR)/ cp -f $(BUILDDIR)/tbot $(BINDIR)/ cp -f $(BUILDDIR)/teleport $(BINDIR)/ cp -f $(BUILDDIR)/teleport-update $(BINDIR)/ mkdir -p $(DATADIR) # Docker image build. Always build the binaries themselves within docker (see # the "docker" rule) to avoid dependencies on the host libc version. .PHONY: image image: OS=linux image: TARBALL_PATH_SECTION:=-s "$(shell pwd)" image: clean docker-binaries build-archive oss-deb cp ./build.assets/charts/Dockerfile $(BUILDDIR)/ cd $(BUILDDIR) && docker build --no-cache . -t $(DOCKER_IMAGE):$(VERSION)-$(ARCH) --target teleport \ --build-arg DEB_PATH="./teleport_$(VERSION)_$(ARCH).deb" if [ -f e/Makefile ]; then $(MAKE) -C e image PIV=$(PIV); fi .PHONY: print-version print-version: @echo $(VERSION) .PHONY: chart-ent chart-ent: $(MAKE) -C e chart RUNTIME_SECTION ?= TARBALL_PATH_SECTION ?= ifneq ("$(RUNTIME)", "") RUNTIME_SECTION := -r $(RUNTIME) endif ifneq ("$(OSS_TARBALL_PATH)", "") TARBALL_PATH_SECTION := -s $(OSS_TARBALL_PATH) endif # build .pkg # builds two package files: tsh-$VERSION.pkg and teleport-bin-$VERSION.pkg # combines the two package files into one teleport-$VERSION.pkg .PHONY: pkg pkg: TELEPORT_PKG_UNSIGNED = $(BUILDDIR)/teleport-$(VERSION).unsigned.pkg pkg: TELEPORT_PKG_SIGNED = $(RELEASE_DIR)/teleport-$(VERSION).pkg pkg: TELEPORT_TOOLS_PKG_UNSIGNED = $(BUILDDIR)/teleport-tools-$(VERSION).unsigned.pkg pkg: TELEPORT_TOOLS_PKG_SIGNED = $(RELEASE_DIR)/teleport-tools-$(VERSION).pkg pkg: | $(RELEASE_DIR) mkdir -p $(BUILDDIR)/ @echo Building tsh-$(VERSION).pkg ./build.assets/build-pkg-app.sh -t oss -v $(VERSION) -b $(TSH_BUNDLEID) -a $(ARCH) $(TARBALL_PATH_SECTION) mv tsh*.pkg* $(BUILDDIR)/ @echo Building tctl-$(VERSION).pkg ./build.assets/build-pkg-app.sh -p tctl -t oss -v $(VERSION) -b $(TCTL_BUNDLEID) -a $(ARCH) $(TARBALL_PATH_SECTION) mv tctl*.pkg* $(BUILDDIR)/ @echo Building teleport-bin-$(VERSION).pkg cp ./build.assets/build-package.sh ./build.assets/build-common.sh $(BUILDDIR)/ chmod +x $(BUILDDIR)/build-package.sh # runtime is currently ignored on OS X # we pass it through for consistency - it will be dropped by the build script cd $(BUILDDIR) && ./build-package.sh -t oss -v $(VERSION) -p pkg -b $(TELEPORT_BUNDLEID) -a $(ARCH) $(RUNTIME_SECTION) $(TARBALL_PATH_SECTION) @echo Combining teleport-bin-$(VERSION).pkg and tsh-$(VERSION).pkg into teleport-$(VERSION).pkg productbuild --package $(BUILDDIR)/tsh*.pkg --package $(BUILDDIR)/tctl*.pkg --package $(BUILDDIR)/teleport-bin*.pkg $(TELEPORT_PKG_UNSIGNED) $(NOTARIZE_TELEPORT_PKG) @echo Combining tsh-$(VERSION).pkg and tctl-$(VERSION).pkg into teleport-tools-$(VERSION).pkg productbuild --package $(BUILDDIR)/tsh*.pkg --package $(BUILDDIR)/tctl*.pkg $(TELEPORT_TOOLS_PKG_UNSIGNED) $(NOTARIZE_TELEPORT_TOOLS_PKG) if [ -f e/Makefile ]; then $(MAKE) -C e pkg; fi # build .rpm .PHONY: rpm rpm: mkdir -p $(BUILDDIR)/ cp ./build.assets/build-package.sh ./build.assets/build-common.sh $(BUILDDIR)/ chmod +x $(BUILDDIR)/build-package.sh cp -a ./build.assets/rpm $(BUILDDIR)/ cp -a ./build.assets/rpm-sign $(BUILDDIR)/ cd $(BUILDDIR) && ./build-package.sh -t oss -v $(VERSION) -p rpm -a $(ARCH) $(RUNTIME_SECTION) $(TARBALL_PATH_SECTION) if [ -f e/Makefile ]; then $(MAKE) -C e rpm; fi # build unsigned .rpm (for testing) .PHONY: rpm-unsigned rpm-unsigned: $(MAKE) UNSIGNED_RPM=true rpm # build open source .deb only .PHONY: oss-deb oss-deb: mkdir -p $(BUILDDIR)/ cp ./build.assets/build-package.sh ./build.assets/build-common.sh $(BUILDDIR)/ chmod +x $(BUILDDIR)/build-package.sh cd $(BUILDDIR) && ./build-package.sh -t oss -v $(VERSION) -p deb -a $(ARCH) $(RUNTIME_SECTION) $(TARBALL_PATH_SECTION) # build .deb .PHONY: deb deb: oss-deb if [ -f e/Makefile ]; then $(MAKE) -C e deb; fi # check binary compatibility with different OSes .PHONY: test-compat test-compat: ./build.assets/build-test-compat.sh .PHONY: ensure-webassets ensure-webassets: # Stage the logo SVGs the Vite build will compress and embed. Runs before the # sha check so a change in GITHUB_REPOSITORY_OWNER produces a different web/ # sha and forces a rebuild. ifeq ("$(GITHUB_REPOSITORY_OWNER)","gravitational") @echo "copying teleport logo assets (community)"; @cp web/packages/design/src/assets/images/community-light.svg web/packages/teleport/public/app/logo-light.svg @cp web/packages/design/src/assets/images/community-dark.svg web/packages/teleport/public/app/logo-dark.svg else @echo "copying teleport logo assets (agpl)"; @cp web/packages/design/src/assets/images/agpl-light.svg web/packages/teleport/public/app/logo-light.svg @cp web/packages/design/src/assets/images/agpl-dark.svg web/packages/teleport/public/app/logo-dark.svg endif @if [[ "${WEBASSETS_SKIP_BUILD}" -eq 1 ]]; then mkdir -p webassets/teleport && mkdir -p webassets/teleport/app && cp web/packages/teleport/index.html webassets/teleport/index.html; \ else MAKE="$(MAKE)" "$(MAKE_DIR)/build.assets/build-webassets-if-changed.sh" OSS webassets/oss-sha build-ui web; fi .PHONY: ensure-webassets-e ensure-webassets-e: @if [[ "${WEBASSETS_SKIP_BUILD}" -eq 1 ]]; then mkdir -p webassets/teleport && mkdir -p webassets/e/teleport/app && cp web/packages/teleport/index.html webassets/e/teleport/index.html; \ else MAKE="$(MAKE)" "$(MAKE_DIR)/build.assets/build-webassets-if-changed.sh" Enterprise webassets/e/e-sha build-ui-e web e/web; fi # Enables the pnpm package manager if it is not already enabled and Corepack # is available. # We check if pnpm is enabled, as the user may not have permission to # enable it, but it may already be available. # Enabling it merely installs a shim which then needs to be downloaded before first use. # Corepack typically prompts before downloading a package manager. We work around that # by issuing a bogus pnpm call with an env var that skips the prompt. .PHONY: ensure-js-package-manager ensure-js-package-manager: @if [ -z "$$(COREPACK_ENABLE_DOWNLOAD_PROMPT=0 pnpm -v 2>/dev/null)" ]; then \ if [ -n "$$(corepack --version 2>/dev/null)" ]; then \ echo 'Info: pnpm is not enabled via Corepack. Enabling pnpm…'; \ corepack enable pnpm; \ echo "pnpm $$(COREPACK_ENABLE_DOWNLOAD_PROMPT=0 pnpm -v)"; \ else \ echo 'Error: Corepack is not installed, cannot enable pnpm. See the installation guide https://pnpm.io/installation#using-corepack'; \ exit 1; \ fi; \ fi .PHONY: init-submodules-e init-submodules-e: git submodule init e git submodule update # backport will automatically create backports for a given PR as long as you have the "gh" tool # installed locally. To backport, type "make backport PR=1234 TO=branch/1,branch/2". .PHONY: backport backport: (cd ./assets/backport && go run main.go -pr=$(PR) -to=$(TO)) .PHONY: ensure-js-deps ensure-js-deps: @if [[ "${WEBASSETS_SKIP_BUILD}" -eq 1 ]]; then mkdir -p webassets/teleport && touch webassets/teleport/index.html; \ else $(MAKE) ensure-js-package-manager && pnpm install --frozen-lockfile; fi .PHONY: ensure-wasm-deps ifeq ($(WEBASSETS_SKIP_BUILD),1) ensure-wasm-deps: else ensure-wasm-deps: rustup-toolchain-warning ensure-wasm-bindgen ensure-wasm-opt WASM_BINDGEN_VERSION = $(shell awk ' \ $$1 == "name" && $$3 == "\"wasm-bindgen\"" { in_pkg=1; next } \ in_pkg && $$1 == "version" { gsub(/"/, "", $$3); print $$3; exit } \ ' Cargo.lock) .PHONY: print-wasm-bindgen-version print-wasm-bindgen-version: @echo $(WASM_BINDGEN_VERSION) RUST_TOOLCHAIN_VERSION = $(shell awk '$$1 == "channel" && $$2 == "=" { gsub(/"/, "", $$3); print $$3 }' rust-toolchain.toml ) .PHONY: print-rust-toolchain-version print-rust-toolchain-version: @echo $(RUST_TOOLCHAIN_VERSION) ensure-wasm-bindgen: NEED_VERSION = $(WASM_BINDGEN_VERSION) ensure-wasm-bindgen: INSTALLED_VERSION = $(word 2,$(shell wasm-bindgen --version 2>/dev/null)) ensure-wasm-bindgen: @: $(or $(NEED_VERSION),$(error Unknown wasm-bindgen version. Is it in Cargo.lock?)) $(if $(filter-out $(INSTALLED_VERSION),$(NEED_VERSION)),\ cargo install wasm-bindgen-cli --force --locked --version "$(NEED_VERSION)", \ @echo wasm-bindgen-cli up-to-date: $(INSTALLED_VERSION) \ ) endif .PHONY: ensure-wasm-opt ensure-wasm-opt: WASM_OPT_VERSION := $(shell $(MAKE) --no-print-directory -C build.assets print-wasm-opt-version) ensure-wasm-opt: cargo install --locked wasm-opt@$(WASM_OPT_VERSION) .PHONY: build-ui build-ui: ensure-js-deps ensure-wasm-deps @[ "${WEBASSETS_SKIP_BUILD}" -eq 1 ] || pnpm build-ui-oss .PHONY: build-ui-e build-ui-e: ensure-js-deps ensure-wasm-deps @[ "${WEBASSETS_SKIP_BUILD}" -eq 1 ] || pnpm build-ui-e .PHONY: docker-ui docker-ui: $(MAKE) -C build.assets ui # TODO(rhammonds): Remove this target once all references to it have # been removed from e submodule and e ref is updated. .PHONY: rustup-set-version rustup-set-version: ; # obsoleted by toolchain file # rustup-install-target-toolchain ensures the required rust compiler is # installed to build for $(ARCH)/$(OS) for the version of rust we use, as # defined in build.assets/Makefile. It assumes that `rustup` is already # installed for managing the rust toolchain. .PHONY: rustup-install-target-toolchain rustup-install-target-toolchain: rustup target add $(RUST_TARGET_ARCH) define rust_toolchain_warning The active Rust toolchain version does not match the toolchain required to build Teleport. This is likely caused by a directory override. You can inspect your current overrides with 'rustup show active-toolchain' and clear directory overrides with 'rustup override unset' endef export rust_toolchain_warning # inspect the current active toolchain and display a warning if it doesn't # match the version defined in our toolchain file. .PHONY: rustup-toolchain-warning rustup-toolchain-warning: EXPECTED = $(shell $(MAKE) print-rust-toolchain-version) rustup-toolchain-warning: @if [ "$(shell rustup show active-toolchain | cut -d'-' -f1)" != "$(EXPECTED)" ]; then \ echo -en "\033[31m";\ echo "$$rust_toolchain_warning";\ echo -en "\033[0m";\ fi # changelog generates PR changelog between the provided base tag and the tip of # the specified branch. # # usage: make changelog # usage: make changelog BASE_BRANCH=branch/v13 BASE_TAG=v13.2.0 # usage: BASE_BRANCH=branch/v13 BASE_TAG=v13.2.0 make changelog # # BASE_BRANCH and BASE_TAG will be automatically determined if not specified. .PHONY: changelog changelog: @go run github.com/gravitational/shared-workflows/tools/changelog@latest \ --base-branch="$(BASE_BRANCH)" --base-tag="$(BASE_TAG)" ./ # create-github-release will generate release notes from the CHANGELOG.md and will # create release notes from them. # # usage: make create-github-release # usage: make create-github-release LATEST=true # # If it detects that the first version in CHANGELOG.md # does not match version set it will fail to create a release. If tag doesn't exist it # will also fail to create a release. # # For more information on release notes generation see: # https://github.com/gravitational/shared-workflows/tree/gus/release-notes/tools/release-notes#readme .PHONY: create-github-release create-github-release: LATEST = false create-github-release: GITHUB_RELEASE_LABELS = "" create-github-release: @NOTES=$$( \ go run github.com/gravitational/shared-workflows/tools/release-notes@latest \ --labels=$(GITHUB_RELEASE_LABELS) $(VERSION) CHANGELOG.md \ ) && gh release create v$(VERSION) \ -t "Teleport $(VERSION)" \ --latest=$(LATEST) \ --verify-tag \ -F - <<< "$$NOTES" .PHONY: go-mod-tidy-all go-mod-tidy-all: find . -type "f" -name "go.mod" -execdir go mod tidy \; .PHONY: dump-preset-roles dump-preset-roles: GOOS=$(OS) GOARCH=$(ARCH) $(CGOFLAG) go run ./build.assets/dump-preset-roles/main.go pnpm test web/packages/teleport/src/Roles/RoleEditor/StandardEditor/standardmodel.test.ts cli-docs: cli-docs-tsh cli-docs-tbot cli-docs-teleport cli-docs-tctl .PHONY: cli-docs-tsh cli-docs-tsh: # Executing go build instead of go run since we don't want to redirect # irrelevant output along with the docs page content. go build -o $(BUILDDIR)/tshdocs -tags docs ./tool/tsh && \ $(BUILDDIR)/tshdocs help >docs/pages/reference/cli/tsh.mdx && \ rm $(BUILDDIR)/tshdocs .PHONY: cli-docs-tbot cli-docs-tbot: # Executing go build instead of go run since we don't want to redirect # irrelevant output along with the docs page content. go build -o $(BUILDDIR)/tbotdocs -tags docs ./tool/tbot && \ $(BUILDDIR)/tbotdocs help >docs/pages/reference/cli/tbot.mdx && \ rm $(BUILDDIR)/tbotdocs .PHONY: cli-docs-teleport cli-docs-teleport: # Executing go build instead of go run since we don't want to redirect # irrelevant output along with the docs page content. go build -o $(BUILDDIR)/teleportdocs -tags docs ./tool/teleport && \ $(BUILDDIR)/teleportdocs help >docs/pages/reference/cli/teleport.mdx && \ rm $(BUILDDIR)/teleportdocs .PHONY: cli-docs-tctl cli-docs-tctl: # Executing go build instead of go run since we don't want to redirect # irrelevant output along with the docs page content. go build -o $(BUILDDIR)/tctldocs -tags docs ./tool/tctl && \ $(BUILDDIR)/tctldocs help >docs/pages/reference/cli/tctl.mdx && \ rm $(BUILDDIR)/tctldocs # cli-docs-up-to-date checks if the generated CLI reference docs are up to date. .PHONY: cli-docs-up-to-date cli-docs-up-to-date: must-start-clean/host cli-docs @if ! git diff --quiet -- docs/pages/reference/cli/; then \ echo ""; \ echo "CLI reference documentation is out of date."; \ echo "Please run 'make cli-docs' and commit the changes."; \ echo ""; \ git diff --stat -- docs/pages/reference/cli/; \ exit 1; \ fi # audit-event-reference generates audit event reference docs using the Web UI # source. .PHONY: audit-event-reference audit-event-reference: pnpm run -C ./web/packages/teleport event-reference # audit-event-reference-up-to-date ensures the audit event reference # documentation reflects the Web UI source. .PHONY: audit-event-reference-up-to-date audit-event-reference-up-to-date: must-start-clean/host audit-event-reference @if ! git diff --quiet; then \ ./build.assets/please-run.sh "audit event reference docs" "make audit-event-reference"; \ exit 1; \ fi .PHONY: access-monitoring-reference access-monitoring-reference: cd ./build.assets/tooling/cmd/gen-athena-docs && go run main.go > ../../../../docs/pages/includes/access-monitoring-events.mdx .PHONY: access-monitoring-reference-up-to-date access-monitoring-reference-up-to-date: access-monitoring-reference @if ! git diff --quiet; then \ ./build.assets/please-run.sh "Access Monitoring event reference docs" "make access-monitoring-reference"; \ exit 1; \ fi .PHONY: gen-docs gen-docs: gen-resource-docs audit-event-reference $(MAKE) -C integrations/terraform docs $(MAKE) -C integrations/operator crd-docs $(MAKE) -C examples/chart render-chart-ref .PHONY: gen-resource-docs gen-resource-docs: cd build.assets/tooling/cmd/resource-ref-generator && go run . -config config.yaml .PHONY: resource-docs-up-to-date resource-docs-up-to-date: must-start-clean/host gen-resource-docs @if ! git diff --quiet; then \ ./build.assets/please-run.sh "tctl resource reference docs" "make gen-resource-docs"; \ exit 1; \ fi .PHONY: benchstat benchstat: ifndef BENCH_FILES $(error "Please provide BENCH_FILES= ...") endif @$(BENCHSTAT) $(BENCH_FILES) | tee test-logs/benchstat.txt