mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-12 02:15:01 +00:00
Better webassets embedding (#17058)
This commit is contained in:
@@ -26,7 +26,6 @@ ifneq ("$(wildcard /bin/bash)","")
|
||||
SHELL := /bin/bash -o pipefail
|
||||
endif
|
||||
BUILDDIR ?= build
|
||||
ASSETS_BUILDDIR ?= lib/web/build
|
||||
BINDIR ?= /usr/local/bin
|
||||
DATADIR ?= /usr/local/share/teleport
|
||||
ADDFLAGS ?=
|
||||
@@ -102,7 +101,7 @@ endif
|
||||
# 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)
|
||||
|
||||
|
||||
with_rdpclient := no
|
||||
RDPCLIENT_MESSAGE := without-Windows-RDP-client
|
||||
|
||||
@@ -343,7 +342,7 @@ endif
|
||||
# only tsh is built.
|
||||
#
|
||||
.PHONY:full
|
||||
full: $(ASSETS_BUILDDIR)/webassets
|
||||
full: ensure-webassets
|
||||
ifneq ("$(OS)", "windows")
|
||||
$(MAKE) all WEBASSETS_TAG="webassets_embed"
|
||||
endif
|
||||
@@ -354,9 +353,7 @@ endif
|
||||
.PHONY:full-ent
|
||||
full-ent:
|
||||
ifneq ("$(OS)", "windows")
|
||||
@if [ -f e/Makefile ]; then \
|
||||
rm $(ASSETS_BUILDDIR)/webassets; \
|
||||
$(MAKE) -C e full; fi
|
||||
@if [ -f e/Makefile ]; then $(MAKE) -C e full; fi
|
||||
endif
|
||||
|
||||
#
|
||||
@@ -428,10 +425,7 @@ release-unix: clean full
|
||||
tar $(TAR_FLAGS) -c teleport | gzip -n > $(RELEASE).tar.gz
|
||||
rm -rf teleport
|
||||
@echo "---> Created $(RELEASE).tar.gz."
|
||||
@if [ -f e/Makefile ]; then \
|
||||
rm -fr $(ASSETS_BUILDDIR)/webassets; \
|
||||
$(MAKE) -C e release; \
|
||||
fi
|
||||
@if [ -f e/Makefile ]; then $(MAKE) -C e release; fi
|
||||
|
||||
#
|
||||
# make release-windows-unsigned - Produces a binary release archive containing only tsh.
|
||||
@@ -854,20 +848,6 @@ update-tag:
|
||||
git tag api/$(GITTAG)
|
||||
git push origin $(GITTAG) && git push origin api/$(GITTAG)
|
||||
|
||||
# build/webassets directory contains the web assets (UI) which get
|
||||
# embedded in the teleport binary
|
||||
$(ASSETS_BUILDDIR)/webassets: ensure-webassets $(ASSETS_BUILDDIR)
|
||||
ifneq ("$(OS)", "windows")
|
||||
@echo "---> Copying OSS web assets."; \
|
||||
rm -rf $(ASSETS_BUILDDIR)/webassets; \
|
||||
mkdir $(ASSETS_BUILDDIR)/webassets; \
|
||||
cd webassets/teleport/ ; cp -r . ../../$@
|
||||
endif
|
||||
|
||||
$(ASSETS_BUILDDIR):
|
||||
mkdir -p $@
|
||||
|
||||
|
||||
.PHONY: test-package
|
||||
test-package: remove-temp-files
|
||||
go test -v ./$(p)
|
||||
|
||||
+1
-1
Submodule e updated: 9a98dc59d5...93a19fd5ed
@@ -4798,8 +4798,8 @@ func getPublicAddr(authClient auth.ReadAppsAccessPoint, a App) (string, error) {
|
||||
// It uses external configuration to make the decision
|
||||
func newHTTPFileSystem() (http.FileSystem, error) {
|
||||
if !isDebugMode() {
|
||||
fs, err := web.NewStaticFileSystem() //nolint:staticcheck
|
||||
if err != nil { //nolint:staticcheck
|
||||
fs, err := teleport.NewWebAssetsFilesystem() //nolint:staticcheck
|
||||
if err != nil { //nolint:staticcheck
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return fs, nil
|
||||
|
||||
@@ -68,36 +68,6 @@ func executableFolder() (string, error) {
|
||||
return filepath.Dir(filepath.Clean(p)), nil
|
||||
}
|
||||
|
||||
const (
|
||||
webAssetsMissingError = "the teleport binary was built without web assets, try building with `make release`"
|
||||
webAssetsReadError = "failure reading web assets from the binary"
|
||||
)
|
||||
|
||||
func readZipArchive(r io.ReaderAt, size int64) (ResourceMap, error) {
|
||||
zreader, err := zip.NewReader(r, size)
|
||||
if err != nil {
|
||||
// this often happens when teleport is launched without the web assets
|
||||
// zip file attached to the binary. for launching it in such mode
|
||||
// set DEBUG environment variable to 1
|
||||
if err == zip.ErrFormat {
|
||||
return nil, trace.NotFound(webAssetsMissingError)
|
||||
}
|
||||
return nil, trace.NotFound("%s %v", webAssetsReadError, err)
|
||||
}
|
||||
entries := make(ResourceMap)
|
||||
for _, file := range zreader.File {
|
||||
if file.FileInfo().IsDir() {
|
||||
continue
|
||||
}
|
||||
entries[file.Name] = file
|
||||
}
|
||||
// no entries found?
|
||||
if len(entries) == 0 {
|
||||
return nil, trace.Wrap(os.ErrInvalid)
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// resource struct implements http.File interface on top of zip.File object
|
||||
type resource struct {
|
||||
reader io.ReadCloser
|
||||
|
||||
@@ -18,11 +18,9 @@ package web
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -43,64 +41,3 @@ func TestLocalFS(t *testing.T) {
|
||||
require.Equal(t, strings.Contains(html, `<script src="/web/config.js"></script>`), true)
|
||||
require.Equal(t, strings.Contains(html, `content="{{ .XCSRF }}"`), true)
|
||||
}
|
||||
|
||||
func TestZipFS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs, err := readZipArchiveAt("../../fixtures/assets.zip")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fs)
|
||||
|
||||
// test simple full read:
|
||||
f, err := fs.Open("/index.html")
|
||||
require.NoError(t, err)
|
||||
bytes, err := io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(bytes), 813)
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
// seek + read
|
||||
f, err = fs.Open("/index.html")
|
||||
require.NoError(t, err)
|
||||
defer f.Close()
|
||||
|
||||
n, err := f.Seek(10, io.SeekStart)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, n, int64(10))
|
||||
|
||||
bytes, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(bytes), 803)
|
||||
|
||||
n, err = f.Seek(-50, io.SeekEnd)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, n, int64(763))
|
||||
bytes, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(bytes), 50)
|
||||
|
||||
_, err = f.Seek(-50, io.SeekEnd)
|
||||
require.NoError(t, err)
|
||||
n, err = f.Seek(-50, io.SeekCurrent)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, n, int64(713))
|
||||
bytes, err = io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(bytes), 100)
|
||||
}
|
||||
|
||||
func readZipArchiveAt(path string) (ResourceMap, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
// file needs to stay open for http.FileSystem reads to work
|
||||
//
|
||||
// feed the binary into the zip reader and enumerate all files
|
||||
// found in the attached zip file:
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return readZipArchive(file, info.Size())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build webassets_embed
|
||||
// +build webassets_embed
|
||||
//go:build webassets_embed && !webassets_ent
|
||||
|
||||
/*
|
||||
Copyright 2021 Gravitational, Inc.
|
||||
@@ -17,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package web
|
||||
package teleport
|
||||
|
||||
import (
|
||||
"embed"
|
||||
@@ -27,13 +26,13 @@ import (
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
//go:embed build/webassets
|
||||
var webassetFS embed.FS
|
||||
//go:embed webassets/teleport
|
||||
var embedded embed.FS
|
||||
|
||||
// NewStaticFileSystem returns the initialized implementation of http.FileSystem
|
||||
// interface which can be used to serve Teleport Proxy Web UI
|
||||
func NewStaticFileSystem() (http.FileSystem, error) {
|
||||
wfs, err := fs.Sub(webassetFS, "build/webassets")
|
||||
// NewWebAssetsFilesystem returns the initialized implementation of
|
||||
// http.FileSystem interface which can be used to serve Teleport Proxy Web UI
|
||||
func NewWebAssetsFilesystem() (http.FileSystem, error) {
|
||||
wfs, err := fs.Sub(embedded, "webassets/teleport")
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//go:build webassets_embed && webassets_ent
|
||||
|
||||
/*
|
||||
Copyright 2021 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package teleport
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
//go:embed webassets/e/teleport
|
||||
var embedded embed.FS
|
||||
|
||||
// NewWebAssetsFilesystem returns the initialized implementation of
|
||||
// http.FileSystem interface which can be used to serve Teleport Proxy Web UI
|
||||
func NewWebAssetsFilesystem() (http.FileSystem, error) {
|
||||
wfs, err := fs.Sub(embedded, "webassets/e/teleport")
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return http.FS(wfs), nil
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !webassets_embed
|
||||
// +build !webassets_embed
|
||||
|
||||
/*
|
||||
Copyright 2021 Gravitational, Inc.
|
||||
@@ -17,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package web
|
||||
package teleport
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -25,7 +24,9 @@ import (
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
// NewStaticFileSystem is a no-op in this build mode.
|
||||
func NewStaticFileSystem() (http.FileSystem, error) { //nolint:staticcheck
|
||||
const webAssetsMissingError = "the teleport binary was built without web assets, try building with `make release`"
|
||||
|
||||
// NewWebAssetsFilesystem is a no-op in this build mode.
|
||||
func NewWebAssetsFilesystem() (http.FileSystem, error) { //nolint:staticcheck
|
||||
return nil, trace.NotFound(webAssetsMissingError)
|
||||
}
|
||||
Reference in New Issue
Block a user