Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaime Martinez <jmartinez@gitlab.com>2021-10-08 02:29:35 +0300
committerJaime Martinez <jmartinez@gitlab.com>2021-10-08 02:29:35 +0300
commit247bd7ba2fd9139711218c6a42ed03c551f958d9 (patch)
tree5f34b0cf1bf51aed35fe35d5396916e89eef5485
parentc48bb316739e39ba1b225f12147fad45337aa711 (diff)
parentbf039d89071e527e2e5c1bc2e64c7513d87cba1a (diff)
Merge branch 'remove/root' into 'master'
Remove gitlab-pages daemon Closes #114 and #133 See merge request gitlab-org/gitlab-pages!542
-rw-r--r--.gitlab/ci/test.yml14
-rw-r--r--README.md102
-rw-r--r--daemon.go189
-rw-r--r--doc/development.md2
-rw-r--r--internal/config/config.go15
-rw-r--r--internal/config/flags.go4
-rw-r--r--main.go18
-rw-r--r--test/acceptance/acceptance_test.go1
-rw-r--r--test/acceptance/helpers_test.go23
9 files changed, 13 insertions, 355 deletions
diff --git a/.gitlab/ci/test.yml b/.gitlab/ci/test.yml
index a29acb7d..ea7b6932 100644
--- a/.gitlab/ci/test.yml
+++ b/.gitlab/ci/test.yml
@@ -20,12 +20,6 @@
- echo "Running just the acceptance tests...."
- make acceptance
-.tests-acceptance-daemonize:
- extends: .tests-common
- script:
- - echo "Running just the acceptance tests as daemon...."
- - make acceptance ARGS='-daemonize'
-
test:1.16:
extends: .tests-unit
image: golang:1.16
@@ -34,10 +28,6 @@ test-acceptance:1.16:
extends: .tests-acceptance
image: golang:1.16
-test-acceptance-daemonize:1.16:
- extends: .tests-acceptance-daemonize
- image: golang:1.16
-
test:1.17:
extends: .tests-unit
image: golang:1.17
@@ -46,10 +36,6 @@ test-acceptance:1.17:
extends: .tests-acceptance
image: golang:1.17
-test-acceptance-daemonize:1.17:
- extends: .tests-acceptance-daemonize
- image: golang:1.17
-
race:
extends: .tests-common
script:
diff --git a/README.md b/README.md
index 6c9729f9..7cc142c5 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-## GitLab Pages Daemon
+## GitLab Pages
[![build status](https://gitlab.com/gitlab-org/gitlab-pages/badges/master/pipeline.svg)](https://gitlab.com/gitlab-org/gitlab-pages/commits/master)
[![coverage report](https://gitlab.com/gitlab-org/gitlab-pages/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-pages/commits/master)
@@ -21,16 +21,16 @@ current requests.
### How it serves content
-1. When client initiates the TLS connection, the GitLab-Pages daemon looks in
+1. When a client initiates the TLS connection, GitLab Pages looks in
the generated configuration for virtual hosts. If present, it uses the TLS
key and certificate in `config.json`, otherwise it falls back to the global
configuration.
-2. When client connects to an HTTP port, the GitLab-Pages daemon looks in the
+1. When a client connects to an HTTP port, GitLab Pages looks in the
generated configuration for a matching virtual host.
-3. The URL.Path is split into `/<project>/<subpath>` and the daemon tries to
+1. The URL.Path is split into `/<project>/<subpath>` and Pages tries to
load: `pages-root/group/project/public/subpath`.
-4. If the file is not found, it will try to load `pages-root/group/<host>/public/<URL.Path>`.
-5. If requested path is a directory, the `index.html` will be served.
+1. If the file is not found, it will try to load `pages-root/group/<host>/public/<URL.Path>`.
+1. If requested path is a directory, the `index.html` file is served.
6. If `.../path.gz` exists, it will be served instead of the main file, with
a `Content-Encoding: gzip` header. This allows compressed versions of the
files to be precalculated, saving CPU time and network bandwidth.
@@ -80,89 +80,6 @@ $ ./gitlab-pages -listen-https ":9090" -root-cert=path/to/example.com.crt -root-
See [doc/development.md](doc/development.md)
-
-### Run daemon **in secure mode**
-
-**Update**:
-
-Starting from GitLab 14.1 the
-[jailing/chroot mechanism is disabled by default](https://docs.gitlab.com/ee/administration/pages/#jailing-mechanism-disabled-by-default-for-api-based-configuration).
-
-When compiled with `CGO_ENABLED=0` (which is the default), `gitlab-pages` is a
-static binary and so can be run in chroot with dropped privileges.
-
-To enter this mode, run `gitlab-pages` as the root user and pass it the
-`-daemon-uid` and `-daemon-gid` arguments to specify the user you want it to run
-as.
-
-The daemon starts listening on ports and reads certificates as root, then
-re-executes itself as the specified user. When re-executing it creates a chroot jail
-containing a copy of its own binary, `/etc/hosts`, `/etc/nsswitch.conf`, `/etc/resolv.conf`, and a bind mount of `pages-root`.
-
-When `-artifacts-server` points to an HTTPS URL we also need a list of certificates for
-the trusted Certification Authorities to copy inside the jail.
-A file containing such list can be specified using `SSL_CERT_FILE` environment variable.
-(`SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt` on Debian)
-
-This makes it possible to listen on privileged ports and makes it harder for the
-process to read files outside of `pages-root`.
-
-Example:
-```
-$ make
-$ sudo ./gitlab-pages -listen-http ":80" -pages-root path/to/gitlab/shared/pages -pages-domain example.com -daemon-uid 1000 -daemon-gid 1000
-```
-
-#### Caveats
-
-The `/etc/hosts`, `/etc/resolv.conf` and `/etc/nsswitch.conf` files, and any file pointed to by the `SSL_CERT_FILE`
-environment variable, will be copied into the jail. As a result, changes to
-these files will not be reflected in Pages until it's restarted.
-
-Bind mounts are unavailable on a range of non-Linux systems. Some of these
-systems (e.g., BSD) offer native "jail" functionality. It is recommended to set
-up an externally-managed jail and run the Pages daemon within it as an ordinary
-user if available.
-
-A less-functional (but just as secure) operation mode is provided via the
-`-daemon-inplace-chroot` command-line option. If passed, Pages will daemonize
-as usual, but chroot directly to the `-pages-root` directory instead of building
-a complete jail in the system temporary directory. There are some known issues
-with this mode, such as:
-
-* Pages service will not be able to resolve the domain name of the auth server and the artifacts server due to missing `/etc/resolv.conf` at the chroot directory. As a workaround, you can manually copy the file to the pages root directory, however, it might cause a conflict with an existing pages data. As a result of DNS not working:
- * [GitLab access control](#gitlab-access-control) might not work
- * [Online view of HTML artifacts](https://about.gitlab.com/2017/10/22/gitlab-10-1-released/#online-view-of-html-artifacts) may not work. You can disable it and fall back to downloading artifacts by setting `artifacts_server` to `false` in `gitlab.yml` for your GitLab instance:
- ```yml
- ## GitLab Pages
- pages:
- enabled: true
- artifacts_server: false
- ```
-* TLS operation (on some systems) will not work
-
-The default secure mode will also fail for certain Linux-based configurations.
-Known cases include:
-
-* The Pages daemon is running inside an unprivileged container
- * Bind mount functionality requires the `CAP_SYS_ADMIN` privilege
- * This is only available to containers run in privileged mode
-* The system temporary directory is mounted `noexec` or `nodev`
- * The jail is created in `$TMPDIR`.
- * Character device files are created within the jail
- * A copy of the gitlab-pages executable is run from within the bind mount
-* AppArmor/SELinux is enabled
- * These systems disallow bind-mounting in certain configurations
-
-In these cases, workarounds are similar to those documented for non-Linux
-systems - use an external jailing technology, or fall back to the pre-v0.8.0
-behaviour using `-daemon-inplace-chroot`.
-
-On Linux, Docker and other containerization systems can be used to build a jail
-within which the Pages daemon can safely run with secure mode disabled. However,
-this configuration **is not secure** if simply using the default
-`gitlab/gitlab-ce` and `gitlab-gitlab-ee` Docker containers!
-
### Listen on multiple ports
Each of the `listen-http`, `listen-https` and `listen-proxy` arguments can be
@@ -224,8 +141,6 @@ $ make
$ ./gitlab-pages -listen-http "10.0.0.1:8080" -listen-https "[fd00::1]:8080" -pages-root path/to/gitlab/shared/pages -pages-domain example.com -auth-client-id <id> -auth-client-secret <secret> -auth-redirect-uri https://projects.example.com/auth -auth-secret something-very-secret -auth-server https://gitlab.com
```
-> NOTE: GitLab access control might not work with `-daemon-inplace-chroot` option. Please take a look at [the caveat section](#caveats) above.
-
#### How it works
1. GitLab pages looks for `access_control` and `id` fields in `config.json` files
@@ -260,8 +175,7 @@ with tools such as [ELK](https://www.elastic.co/elk-stack).
### Cross-origin requests
GitLab Pages defaults to allowing cross-origin requests for any resource it
-serves. This can be disabled globally by passing `-disable-cross-origin-requests`
-when starting the daemon.
+serves. This can be disabled globally by passing `-disable-cross-origin-requests`.
Having cross-origin requests enabled allows third-party websites to make use of
files stored on the Pages server, which allows various third-party integrations
@@ -289,7 +203,7 @@ Example:
### Configuration
-The daemon can be configured with any combination of these methods:
+Gitlab Pages can be configured with any combination of these methods:
1. Command-line options
1. Environment variables
1. Configuration file
diff --git a/daemon.go b/daemon.go
deleted file mode 100644
index 86ede6be..00000000
--- a/daemon.go
+++ /dev/null
@@ -1,189 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "os"
- "os/exec"
- "os/signal"
- "path/filepath"
- "strings"
- "syscall"
-
- "github.com/sirupsen/logrus"
-
- "gitlab.com/gitlab-org/gitlab-pages/internal/config"
-)
-
-const (
- daemonRunProgram = "gitlab-pages-unprivileged"
-)
-
-func daemonMain() {
- if os.Args[0] != daemonRunProgram {
- return
- }
-
- // Validate that a working directory is valid
- // https://man7.org/linux/man-pages/man2/getcwd.2.html
- wd, err := os.Getwd()
- if err != nil {
- fatal(err, "could not get current working directory")
- } else if strings.HasPrefix(wd, "(unreachable)") {
- fatal(os.ErrPermission, "could not get current working directory")
- }
-
- logrus.WithFields(logrus.Fields{
- "uid": syscall.Getuid(),
- "gid": syscall.Getgid(),
- "wd": wd,
- }).Info("starting the daemon as unprivileged user")
-
- // read the configuration from the pipe "ExtraFiles"
- var config config.Config
- if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&config); err != nil {
- fatal(err, "could not decode app config")
- }
- runApp(&config)
- os.Exit(0)
-}
-
-func daemonReexec(uid, gid uint, args ...string) (cmd *exec.Cmd, err error) {
- path, err := os.Executable()
- if err != nil {
- return
- }
-
- cmd = &exec.Cmd{
- Path: path,
- Args: args,
- Env: os.Environ(),
- Stdin: os.Stdin,
- Stdout: os.Stdout,
- Stderr: os.Stderr,
- SysProcAttr: &syscall.SysProcAttr{
- Credential: &syscall.Credential{
- Uid: uint32(uid),
- Gid: uint32(gid),
- },
- Setsid: true,
- },
- }
- return
-}
-
-func daemonUpdateFd(cmd *exec.Cmd, fd uintptr) (childFd uintptr) {
- file := os.NewFile(fd, "[socket]")
-
- // we add 3 since, we have a 3 predefined FDs
- childFd = uintptr(3 + len(cmd.ExtraFiles))
- cmd.ExtraFiles = append(cmd.ExtraFiles, file)
-
- return
-}
-
-func daemonUpdateFds(cmd *exec.Cmd, fds []uintptr) {
- for idx, fd := range fds {
- fds[idx] = daemonUpdateFd(cmd, fd)
- }
-}
-
-func killProcess(cmd *exec.Cmd) {
- if cmd.Process != nil {
- cmd.Process.Kill()
- }
- cmd.Wait()
- for _, file := range cmd.ExtraFiles {
- file.Close()
- }
-}
-
-func passSignals(cmd *exec.Cmd) {
- if cmd.Process == nil {
- return
- }
-
- s := make(chan os.Signal, 1)
- signal.Notify(s, syscall.SIGTERM, os.Interrupt, os.Kill)
-
- go func() {
- for cmd.Process != nil {
- cmd.Process.Signal(<-s)
- }
- }()
-}
-
-func daemonize(config *config.Config) error {
- uid := config.Daemon.UID
- gid := config.Daemon.GID
- pagesRoot := config.General.RootDir
-
- // Ensure pagesRoot is an absolute path. This will produce a different path
- // if any component of pagesRoot is a symlink (not likely). For example,
- // -pages-root=/some-path where ln -s /other-path /some-path
- // pagesPath will become: /other-path and we will fail to serve files from /some-path.
- // GitLab Rails also resolves the absolute path for `pages_path`
- // https://gitlab.com/gitlab-org/gitlab/blob/981ad651d8bd3690e28583eec2363a79f775af89/config/initializers/1_settings.rb#L296
- pagesRoot, err := filepath.Abs(pagesRoot)
- if err != nil {
- return err
- }
-
- logrus.WithFields(logrus.Fields{
- "uid": uid,
- "gid": gid,
- "pages-root": pagesRoot,
- }).Info("running the daemon as unprivileged user")
-
- cmd, err := daemonReexec(uid, gid, daemonRunProgram)
- if err != nil {
- return err
- }
- defer killProcess(cmd)
-
- // Create a pipe to pass the configuration
- configReader, configWriter, err := os.Pipe()
- if err != nil {
- return err
- }
- defer configWriter.Close()
- cmd.ExtraFiles = append(cmd.ExtraFiles, configReader)
-
- updateFds(config, cmd)
-
- // Start the process
- if err := cmd.Start(); err != nil {
- logrus.WithError(err).Error("start failed")
- return err
- }
-
- // Write the configuration
- if err := json.NewEncoder(configWriter).Encode(config); err != nil {
- return err
- }
- configWriter.Close()
-
- // Pass through signals
- passSignals(cmd)
-
- // Wait for process to exit
- return cmd.Wait()
-}
-
-func updateFds(config *config.Config, cmd *exec.Cmd) {
- for _, fds := range [][]uintptr{
- config.Listeners.HTTP,
- config.Listeners.HTTPS,
- config.Listeners.Proxy,
- config.Listeners.HTTPSProxyv2,
- } {
- daemonUpdateFds(cmd, fds)
- }
-
- for _, fdPtr := range []*uintptr{
- &config.ListenMetrics,
- } {
- if *fdPtr != 0 {
- *fdPtr = daemonUpdateFd(cmd, *fdPtr)
- }
- }
-}
diff --git a/doc/development.md b/doc/development.md
index d3de429f..91be0e33 100644
--- a/doc/development.md
+++ b/doc/development.md
@@ -171,7 +171,7 @@ This is an example of developing GitLab Pages inside the [GitLab Development Kit
# Inside $GDK_ROOT/gitlab-pages
$ gdk stop gitlab-pages
$ make # calls go build in this project and creates a `gitlab-pages` binary under bin/
- # start daemon manually with a config
+ # start Pages manually with a config
$ ./bin/gitlab-pages -config gitlab-pages.conf
```
diff --git a/internal/config/config.go b/internal/config/config.go
index 61767a57..94c22328 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -18,7 +18,6 @@ type Config struct {
General General
ArtifactsServer ArtifactsServer
Authentication Auth
- Daemon Daemon
GitLab GitLab
Listeners Listeners
Log Log
@@ -80,12 +79,6 @@ type Auth struct {
Scope string
}
-// Daemon groups settings related to configuring GitLab Pages daemon
-type Daemon struct {
- UID uint
- GID uint
-}
-
// Cache configuration for GitLab API
type Cache struct {
CacheExpiry time.Duration
@@ -215,10 +208,6 @@ func loadConfig() (*Config, error) {
RedirectURI: *redirectURI,
Scope: *authScope,
},
- Daemon: Daemon{
- UID: *daemonUID,
- GID: *daemonGID,
- },
Log: Log{
Format: *logFormat,
Verbose: *logVerbose,
@@ -281,8 +270,6 @@ func LogConfig(config *Config) {
log.WithFields(log.Fields{
"artifacts-server": *artifactsServer,
"artifacts-server-timeout": *artifactsServerTimeout,
- "daemon-gid": *daemonGID,
- "daemon-uid": *daemonUID,
"default-config-filename": flag.DefaultConfigFlagname,
"disable-cross-origin-requests": *disableCrossOriginRequests,
"domain": config.General.Domain,
@@ -313,7 +300,7 @@ func LogConfig(config *Config) {
"zip-cache-cleanup": config.Zip.CleanupInterval,
"zip-cache-refresh": config.Zip.RefreshInterval,
"zip-open-timeout": config.Zip.OpenTimeout,
- }).Debug("Start daemon with configuration")
+ }).Debug("Start Pages with configuration")
}
// LoadConfig parses configuration settings passed as command line arguments or
diff --git a/internal/config/flags.go b/internal/config/flags.go
index aa5bf1c5..52b7be18 100644
--- a/internal/config/flags.go
+++ b/internal/config/flags.go
@@ -21,8 +21,8 @@ var (
metricsAddress = flag.String("metrics-address", "", "The address to listen on for metrics requests")
sentryDSN = flag.String("sentry-dsn", "", "The address for sending sentry crash reporting to")
sentryEnvironment = flag.String("sentry-environment", "", "The environment for sentry crash reporting")
- daemonUID = flag.Uint("daemon-uid", 0, "Drop privileges to this user")
- daemonGID = flag.Uint("daemon-gid", 0, "Drop privileges to this group")
+ _ = flag.Uint("daemon-uid", 0, "DEPRECATED and ignored, will be removed in 15.0")
+ _ = flag.Uint("daemon-gid", 0, "DEPRECATED and ignored, will be removed in 15.0")
_ = flag.Bool("daemon-enable-jail", false, "DEPRECATED and ignored, will be removed in 15.0")
_ = flag.Bool("daemon-inplace-chroot", false, "DEPRECATED and ignored, will be removed in 15.0") // TODO: https://gitlab.com/gitlab-org/gitlab-pages/-/issues/599
propagateCorrelationID = flag.Bool("propagate-correlation-id", false, "Reuse existing Correlation-ID from the incoming request header `X-Request-ID` if present")
diff --git a/main.go b/main.go
index f2f1d69b..8d7af93a 100644
--- a/main.go
+++ b/main.go
@@ -5,7 +5,6 @@ import (
"io"
"math/rand"
"os"
- "strings"
"time"
"github.com/sirupsen/logrus"
@@ -71,7 +70,7 @@ func appMain() {
log.WithFields(log.Fields{
"version": VERSION,
"revision": REVISION,
- }).Info("GitLab Pages Daemon")
+ }).Info("GitLab Pages")
log.Info("URL: https://gitlab.com/gitlab-org/gitlab-pages")
if err := os.Chdir(config.General.RootDir); err != nil {
@@ -85,20 +84,6 @@ func appMain() {
defer closeAll(cs)
}
- if config.Daemon.UID != 0 || config.Daemon.GID != 0 {
- if err := daemonize(config); err != nil {
- if strings.Contains(err.Error(), "signal:") {
- log.WithField("signal", err.Error()).Info("daemon received signal")
- return
- }
-
- errortracking.Capture(err)
- fatal(err, "could not create pages daemon")
- }
-
- return
- }
-
runApp(config)
}
@@ -205,6 +190,5 @@ func main() {
metrics.MustRegister()
- daemonMain()
appMain()
}
diff --git a/test/acceptance/acceptance_test.go b/test/acceptance/acceptance_test.go
index b36bd63d..3b41eaee 100644
--- a/test/acceptance/acceptance_test.go
+++ b/test/acceptance/acceptance_test.go
@@ -18,7 +18,6 @@ const (
var (
pagesBinary = flag.String("gitlab-pages-binary", "../../gitlab-pages", "Path to the gitlab-pages binary")
- daemonize = flag.Bool("daemonize", false, "run tests as daemon")
httpPort = "36000"
httpsPort = "37000"
diff --git a/test/acceptance/helpers_test.go b/test/acceptance/helpers_test.go
index d9f2f14c..e2e1c1d0 100644
--- a/test/acceptance/helpers_test.go
+++ b/test/acceptance/helpers_test.go
@@ -352,7 +352,6 @@ func getPagesArgs(t *testing.T, listeners []ListenSpec, promPort string, extraAr
args = append(args, "-metrics-address", promPort)
}
- args = append(args, getPagesDaemonArgs(t)...)
args = append(args, extraArgs...)
return
@@ -367,28 +366,6 @@ func contains(slice []string, s string) bool {
return false
}
-func getPagesDaemonArgs(t *testing.T) []string {
- if !(*daemonize) {
- return nil
- }
-
- if os.Geteuid() != 0 {
- t.Log("Privilege-dropping requested but not running as root!")
- t.FailNow()
- return nil
- }
-
- out := []string{}
-
- t.Log("Running pages as a daemon")
-
- // This triggers the drop-privileges-and-chroot code in the pages daemon
- out = append(out, "-daemon-uid", "0")
- out = append(out, "-daemon-gid", "65534")
-
- return out
-}
-
// Does a HTTP(S) GET against the listener specified, setting a fake
// Host: and constructing the URL from the listener and the URL suffix.
func GetPageFromListener(t *testing.T, spec ListenSpec, host, urlsuffix string) (*http.Response, error) {