* Move configuration from lib/service to lib/service/servicecfg
The new servicecfg package will hold only configuration for services.
This will allow other packages (like tctl and tsh) to depend on
servicecfg without pulling in all of lib/service (which has a number
of platform-specific details).
This is the first step towards being able to build tctl for Windows.
* Move PAM and BPF config into servicecfg
This breaks a compile-time dependency on BPF/PAM for tctl.
Update metalinter, fix a few lint warnings and replace deprecated linters.
`deadcode`, `structcheck` and `varcheck` are abandoned and now replaced by [`unused`][1].
Since 1.19, `go fmt` reformats godocs according to https://go.dev/doc/comment. I've done a bulk-reformatting of the codebase to keep the linter happy. Backporting is mostly harmless (the exception being `lib/services/role_test.go`, that for some reason breaks the _old_ linter using the new format).
[1]: https://golangci-lint.run/usage/linters/
* Bump golangci-lint version
* Replace abandoned linters
* Fix bodyclose on lib/auth/github.com
* Fix bodyclose on lib/kube/proxy/streamproto/proto_test.go
* Fix bodyclose on lib/srv/alpnproxy/proxy_test.go
* Fix bodyclose on lib/web/conn_upgrade_test.go
* Silence staticcheck on lib/kube/proxy/forwarder_test.go
* Silence staticcheck on lib/utils/certs_test.go
* Address BuildNameToCertificate deprecation warnings
* Run `go fmt ./...`
* Run `go fmt ./...` on api/
* Ignore formatting in role_test.go
* Remove redundant initializers in lib/srv/uacc/
* Update e/
- Don't assume an explicit $GOPATH is set
- Remove golint from linters - it's been deprecated for over a year
and golangci-lint prints a warning instead of running it.
* Update logrus package to fix data races
* Introduce a logger that uses the test context to log the messages so they are output if a test fails for improved trouble-shooting.
* Revert introduction of test logger - simply leave logger configuration at debug level outputting to stderr during tests.
* Run integration test for e as well
* Use make with a cap and append to only copy the relevant roles.
* Address review comments
* Update integration test suite to use test-local logger that would only output logs iff a specific test has failed - no logs from other test cases will be output.
* Revert changes to InitLoggerForTests API
* Create a new logger instance when applying defaults or merging with file service configuration
* Introduce a local logger interface to be able to test file configuration merge.
* Fix kube integration tests w.r.t log
* Move goroutine profile dump into a separate func to handle parameters consistently for all invocations
Most users won't need this, so the behavior is optional. Default system
configs will usually trigger a password prompt, which is why this
feature is disabled by default.
`require` is a sister package to `assert` that terminates the test on
failure. `assert` records the failure but lets the test proceed, which
is un-intuitive.
Also update all existing tests to match.
When you have `libpam-devel` installed, PAM support in teleport gets
enabled. But when you didn't run `make -C build.assets/pam install`, the
configuration that `lib/pam` tests rely on is not in place.
This causes test failures which may be confusing for newcomers who
happen to have `libpam-devel` installed.
Manually check that all services and `pam_teleport.so` are installed
before running the tests, to avoid annoying failures.
Also, refactor PAM tests to the new style.
Lock all PAM commands to the startup thread. From LockOSThread docs:
All init functions are run on the startup thread. Calling LockOSThread from
an init function will cause the main function to be invoked on that thread.
This is needed for pam_loginuid.so. It writes "/proc/self/loginuid"
which, on Linux, depends on being called from a specific thread. If
it's not running on the right thread, pam_loginuid.so may fail with
EPERM sporadically.
> Why the startup thread specifically?
The kernel does some validation based on the thread context. I could
not find what the kernel uses specifically. Some relevant code:
https://github.com/torvalds/linux/blob/9d99b1647fa56805c1cfef2d81ee7b9855359b62/kernel/audit.c#L2284-L2317
Locking to the startup thread seems to make the kernel happy.
> Why not call LockOSThread from pam.Open?
By the time pam.Open gets called, more goroutines could've been
spawned. This means that the main goroutine (running pam.Open) could
get re-scheduled to a different thread.
> Why does pam.Open run on the main goroutine?
This is an assumption. As of today, this is true because teleport
re-executes itself and calls pam.Open synchronously. If we change this
later, loginuid can become flaky again.
> What does OpenSSH do?
OpenSSH has a separate "authentication thread" which does all the PAM
stuff:
https://github.com/openssh/openssh-portable/blob/598c3a5e3885080ced0d7c40fde00f1d5cdbb32b/auth-pam.c#L470-L474
* pam: trigger pam_authenticate on login
This will trigger any "auth" PAM modules configured on the system for
teleport. For example, Duo 2FA prompt on each connection.
The module will be able to interact with the user (e.g. print prompts).
Also, make PAM env var propagation consistent for port forwarding
sessions.
Fixes https://github.com/gravitational/teleport/issues/3929
* Revamp PAM testing stack
- update PAM policies and module for "auth" step
- use pam_teleport.so from the repo directory instead of guessing
OS-specific global path
- add tests covering all failure scenarios and generally refactor PAM
tests
* Build pam_teleport.so during buildbox build inside docker
This removes the need for libpam-devel on the host and reliably compiles
pam_teleport.so in our CI pipeline.
As part of this, combine build.assets/pam/ and modules/pam_teleport to
avoid the need to sync them.
Using `pam_putenv` from `libpam` exposes these env vars to `pam_exec.so`
and possibly other built-in PAM modules. Keep setting them via
`os.Setenv` too, for `pam_script.so` to use.
Updates #3692
Refactored launching of shell to call PAM first. This allows a PAM
module to create the user and home directory before attempting to launch
a shell for said user.
To do this the command passed to Teleport during re-exec has changed.
Before the Teleport master process would resolve the user fully (UID,
GUID, supplementary groups, shell, home directory) before re-launching
itself to then launch a shell. However, if PAM is used to create the
user on the fly and PAM has not been called yet, this will fail.
Instead that work has now been pushed to occur in the child process.
This means the Teleport master process now creates a payload with the
minimum needed from *srv.ServerContext and will then re-exec itself. The
child process will call PAM and then attempt to resolve the user (UID,
GUID, supplementary groups, shell, home directory).
Many applications don't respect the maximum PAM message size
PAM_MAX_MSG_SIZE. To interoperate with those applications, increase the
maximum message size to around 1 MB.