mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-12 02:15:01 +00:00
Update golangci-lint to 1.49.0 (#16507)
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/
This commit is contained in:
+7
-4
@@ -6,6 +6,12 @@ issues:
|
||||
- linters:
|
||||
- revive
|
||||
text: "exported: exported const"
|
||||
# TODO(codingllama): Remove ignore after the new golangci-lint image lands.
|
||||
# For some reason this particular files causes problems between different
|
||||
# goimports versions.
|
||||
- path: lib/services/role_test.go
|
||||
linters:
|
||||
- goimports
|
||||
exclude-use-default: true
|
||||
max-same-issues: 0
|
||||
max-issues-per-linter: 0
|
||||
@@ -14,7 +20,6 @@ linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- goimports
|
||||
- gosimple
|
||||
@@ -23,10 +28,8 @@ linters:
|
||||
- misspell
|
||||
- revive
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- unused
|
||||
- unconvert
|
||||
- varcheck
|
||||
- unused
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
|
||||
@@ -298,10 +298,10 @@ func New(cfg Config) (*CircuitBreaker, error) {
|
||||
}
|
||||
|
||||
// Execute calls the provided function depending on the CircuitBreaker state.
|
||||
// - StateStandby: all functions are executed.
|
||||
// - StateTripped: no functions are executed and ErrStateTripped is returned.
|
||||
// - StateRecovering: some functions are executed, some functions are not,
|
||||
// when not executed ErrLimitExceeded is returned.
|
||||
// - StateStandby: all functions are executed.
|
||||
// - StateTripped: no functions are executed and ErrStateTripped is returned.
|
||||
// - StateRecovering: some functions are executed, some functions are not,
|
||||
// when not executed ErrLimitExceeded is returned.
|
||||
//
|
||||
// The CircuitBreaker state is updated according to the outcome of executing the
|
||||
// provided function and the current state. See package docs for a more detailed
|
||||
|
||||
@@ -30,5 +30,4 @@
|
||||
//
|
||||
// * Config.OnTripped is called on transition (StateStandby -> StateTripped)
|
||||
// * Config.OnStandBy is called on transition (StateRecovering -> StateStandby)
|
||||
//
|
||||
package breaker
|
||||
|
||||
@@ -83,7 +83,8 @@ func (c *tlsConfigCreds) SSHClientConfig() (*ssh.ClientConfig, error) {
|
||||
// KeyPair Credentials can only be used to connect directly to a Teleport Auth server.
|
||||
//
|
||||
// New KeyPair files can be generated with tsh or tctl.
|
||||
// $ tctl auth sign --format=tls --user=api-user --out=path/to/certs
|
||||
//
|
||||
// $ tctl auth sign --format=tls --user=api-user --out=path/to/certs
|
||||
//
|
||||
// The certificates' time to live can be specified with --ttl.
|
||||
//
|
||||
@@ -142,8 +143,9 @@ func (c *keypairCreds) SSHClientConfig() (*ssh.ClientConfig, error) {
|
||||
// or through a reverse tunnel.
|
||||
//
|
||||
// A new identity file can be generated with tsh or tctl.
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
//
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
//
|
||||
// The identity file's time to live can be specified with --ttl.
|
||||
//
|
||||
@@ -212,8 +214,9 @@ func (c *identityCredsFile) load() error {
|
||||
// or through a reverse tunnel.
|
||||
//
|
||||
// A new identity file can be generated with tsh or tctl.
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
//
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
//
|
||||
// The identity file's time to live can be specified with --ttl.
|
||||
//
|
||||
@@ -288,7 +291,8 @@ func (c *identityCredsString) load() error {
|
||||
// tunnel address and make a connection through it.
|
||||
//
|
||||
// A new profile can be generated with tsh.
|
||||
// $ tsh login --user=api-user
|
||||
//
|
||||
// $ tsh login --user=api-user
|
||||
func LoadProfile(dir, name string) Credentials {
|
||||
return &profileCreds{
|
||||
dir: dir,
|
||||
|
||||
+15
-7
@@ -129,7 +129,9 @@ func ExampleNew() {
|
||||
}
|
||||
|
||||
// Generate tsh profile with tsh.
|
||||
// $ tsh login --user=api-user
|
||||
//
|
||||
// $ tsh login --user=api-user
|
||||
//
|
||||
// Load credentials from the default directory and current profile, or specify the directory and profile.
|
||||
func ExampleCredentials_loadProfile() {
|
||||
client.LoadProfile("", "")
|
||||
@@ -143,8 +145,10 @@ func ExampleLoadProfile() {
|
||||
}
|
||||
|
||||
// Generate identity file with tsh or tctl.
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
//
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
//
|
||||
// Load credentials from the specified identity file.
|
||||
func ExampleCredentials_loadIdentity() {
|
||||
client.LoadIdentityFile("identity-file-path")
|
||||
@@ -156,9 +160,11 @@ func ExampleLoadIdentityFile() {
|
||||
}
|
||||
|
||||
// Generate identity file with tsh or tctl.
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
// $ export TELEPORT_IDENTITY=$(cat identity-file-path)
|
||||
//
|
||||
// $ tsh login --user=api-user --out=identity-file-path
|
||||
// $ tctl auth sign --user=api-user --out=identity-file-path
|
||||
// $ export TELEPORT_IDENTITY=$(cat identity-file-path)
|
||||
//
|
||||
// Load credentials from the envrironment variable.
|
||||
func ExampleCredentials_loadIdentityString() {
|
||||
client.LoadIdentityFileFromString(os.Getenv("TELEPORT_IDENTITY"))
|
||||
@@ -170,7 +176,9 @@ func ExampleLoadIdentityFileFromString() {
|
||||
}
|
||||
|
||||
// Generate certificate key pair with tctl.
|
||||
// $ tctl auth sign --format=tls --user=api-user --out=path/to/certs
|
||||
//
|
||||
// $ tctl auth sign --format=tls --user=api-user --out=path/to/certs
|
||||
//
|
||||
// Load credentials from the specified certificate files.
|
||||
func ExampleCredentials_loadKeyPair() {
|
||||
client.LoadKeyPair(
|
||||
|
||||
@@ -105,8 +105,9 @@ func newWebClient(cfg *Config) (*http.Client, error) {
|
||||
|
||||
// doWithFallback attempts to execute an HTTP request using https, and then
|
||||
// fall back to plain HTTP under certain, very specific circumstances.
|
||||
// * The caller must specifically allow it via the allowPlainHTTP parameter, and
|
||||
// * The target host must resolve to the loopback address.
|
||||
// - The caller must specifically allow it via the allowPlainHTTP parameter, and
|
||||
// - The target host must resolve to the loopback address.
|
||||
//
|
||||
// If these conditions are not met, then the plain-HTTP fallback is not allowed,
|
||||
// and a the HTTPS failure will be considered final.
|
||||
func doWithFallback(clt *http.Client, allowPlainHTTP bool, extraHeaders map[string]string, req *http.Request) (*http.Response, error) {
|
||||
|
||||
@@ -49,7 +49,6 @@ const (
|
||||
//
|
||||
// Profiles can be stored in a profile file, allowing TSH users to
|
||||
// type fewer CLI args.
|
||||
//
|
||||
type Profile struct {
|
||||
// WebProxyAddr is the host:port the web proxy can be accessed at.
|
||||
WebProxyAddr string `yaml:"web_proxy_addr,omitempty"`
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
+12
-13
@@ -32,24 +32,23 @@ import (
|
||||
//
|
||||
// Example: assume you have two structs:
|
||||
//
|
||||
// type A struct {
|
||||
// Name string `json:"name"`
|
||||
// Age int `json:"age"`
|
||||
// }
|
||||
// type A struct {
|
||||
// Name string `json:"name"`
|
||||
// Age int `json:"age"`
|
||||
// }
|
||||
//
|
||||
// type B struct {
|
||||
// FullName string `json:"name"`
|
||||
// }
|
||||
// type B struct {
|
||||
// FullName string `json:"name"`
|
||||
// }
|
||||
//
|
||||
// Now you can convert B to A:
|
||||
//
|
||||
// b := &B{ FullName: "Bob Dilan"}
|
||||
// var a *A
|
||||
// utils.ObjectToStruct(b, &a)
|
||||
// fmt.Println(a.Name)
|
||||
//
|
||||
// > "Bob Dilan"
|
||||
// b := &B{ FullName: "Bob Dilan"}
|
||||
// var a *A
|
||||
// utils.ObjectToStruct(b, &a)
|
||||
// fmt.Println(a.Name)
|
||||
//
|
||||
// > "Bob Dilan"
|
||||
func ObjectToStruct(in interface{}, out interface{}) error {
|
||||
bytes, err := json.Marshal(in)
|
||||
if err != nil {
|
||||
|
||||
@@ -165,9 +165,7 @@ ENV GOPATH="/go" \
|
||||
RUN go install github.com/google/[email protected]
|
||||
|
||||
# Install golangci-lint.
|
||||
RUN (curl -L https://github.com/golangci/golangci-lint/releases/download/v1.46.0/golangci-lint-1.46.0-$(go env GOOS)-$(go env GOARCH).tar.gz | tar -xz && \
|
||||
cp golangci-lint-1.46.0-$(go env GOOS)-$(go env GOARCH)/golangci-lint /bin/ && \
|
||||
rm -r golangci-lint*)
|
||||
RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.49.0
|
||||
|
||||
# Install helm.
|
||||
RUN (mkdir -p helm-tarball && curl -L https://get.helm.sh/helm-v3.5.2-$(go env GOOS)-$(go env GOARCH).tar.gz | tar -C helm-tarball -xz && \
|
||||
|
||||
@@ -18,23 +18,25 @@ of Linux servers via SSH or HTTPS. It is intended to be used instead of sshd.
|
||||
|
||||
Teleport enables teams to easily adopt the best SSH practices like:
|
||||
|
||||
- No need to distribute keys: Teleport uses certificate-based access with
|
||||
automatic expiration time.
|
||||
- Enforcement of 2nd factor authentication.
|
||||
- Cluster introspection: every Teleport node becomes a part of a cluster
|
||||
and is visible on the Web UI.
|
||||
- Record and replay SSH sessions for knowledge sharing and auditing purposes.
|
||||
- Collaboratively troubleshoot issues through session sharing.
|
||||
- Connect to clusters located behind firewalls without direct Internet
|
||||
access via SSH bastions.
|
||||
- Ability to integrate SSH credentials with your organization identities
|
||||
via OAuth (Google Apps, Github).
|
||||
- Keep the full audit log of all SSH sessions within a cluster.
|
||||
- No need to distribute keys: Teleport uses certificate-based access with
|
||||
automatic expiration time.
|
||||
- Enforcement of 2nd factor authentication.
|
||||
- Cluster introspection: every Teleport node becomes a part of a cluster
|
||||
and is visible on the Web UI.
|
||||
- Record and replay SSH sessions for knowledge sharing and auditing purposes.
|
||||
- Collaboratively troubleshoot issues through session sharing.
|
||||
- Connect to clusters located behind firewalls without direct Internet
|
||||
access via SSH bastions.
|
||||
- Ability to integrate SSH credentials with your organization identities
|
||||
via OAuth (Google Apps, Github).
|
||||
- Keep the full audit log of all SSH sessions within a cluster.
|
||||
|
||||
Teleport web site:
|
||||
|
||||
https://gravitational.com/teleport/
|
||||
|
||||
Teleport on Github:
|
||||
|
||||
https://github.com/gravitational/teleport
|
||||
*/
|
||||
package teleport
|
||||
|
||||
@@ -31,11 +31,11 @@ func promoteBuildOsRepoPipelines() []pipeline {
|
||||
|
||||
// Used for one-off migrations of older versions.
|
||||
// Use cases include:
|
||||
// * We want to support another OS while providing backwards compatibility
|
||||
// * We want to support another OS version while providing backwards compatibility
|
||||
// * A customer wants to be able to install an older version via APT/YUM even if we
|
||||
// no longer support it
|
||||
// * RPM migrations after new YUM pipeline is done
|
||||
// - We want to support another OS while providing backwards compatibility
|
||||
// - We want to support another OS version while providing backwards compatibility
|
||||
// - A customer wants to be able to install an older version via APT/YUM even if we
|
||||
// no longer support it
|
||||
// - RPM migrations after new YUM pipeline is done
|
||||
func artifactMigrationPipeline() []pipeline {
|
||||
migrationVersions := []string{
|
||||
// These versions were migrated as a part of the new `promoteAptPipeline`
|
||||
|
||||
+1
-1
Submodule e updated: 783e9694a1...4501f659ac
@@ -1213,13 +1213,11 @@ func tlsClientConfig(cfg *rest.Config) (*tls.Config, error) {
|
||||
return nil, trace.BadParameter("failed to append certs from PEM")
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
return &tls.Config{
|
||||
RootCAs: pool,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
}
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
return tlsConfig, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func kubeProxyTLSConfig(cfg kube.ProxyConfig) (*tls.Config, error) {
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -42,10 +42,10 @@ import (
|
||||
)
|
||||
|
||||
// TestGenerateAndUpsertRecoveryCodes tests the following:
|
||||
// - generation of recovery codes are of correct format
|
||||
// - recovery codes are upserted
|
||||
// - recovery codes can be verified and marked used
|
||||
// - reusing a used or non-existing token returns error
|
||||
// - generation of recovery codes are of correct format
|
||||
// - recovery codes are upserted
|
||||
// - recovery codes can be verified and marked used
|
||||
// - reusing a used or non-existing token returns error
|
||||
func TestGenerateAndUpsertRecoveryCodes(t *testing.T) {
|
||||
t.Parallel()
|
||||
srv := newTestTLSServer(t)
|
||||
|
||||
+13
-9
@@ -1040,11 +1040,12 @@ type githubAuthRawResponse struct {
|
||||
HostSigners []json.RawMessage `json:"host_signers"`
|
||||
}
|
||||
|
||||
/* validateGithubAuthRequest validates Github auth callback redirect
|
||||
/*
|
||||
validateGithubAuthRequest validates Github auth callback redirect
|
||||
|
||||
POST /:version/github/requests/validate
|
||||
POST /:version/github/requests/validate
|
||||
|
||||
Success response: githubAuthRawResponse
|
||||
Success response: githubAuthRawResponse
|
||||
*/
|
||||
func (s *APIServer) validateGithubAuthCallback(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
||||
var req validateGithubAuthCallbackReq
|
||||
@@ -1085,9 +1086,10 @@ func (s *APIServer) validateGithubAuthCallback(auth ClientI, w http.ResponseWrit
|
||||
// HTTP GET /:version/events?query
|
||||
//
|
||||
// Query fields:
|
||||
// 'from' : time filter in RFC3339 format
|
||||
// 'to' : time filter in RFC3339 format
|
||||
// ... : other fields are passed directly to the audit backend
|
||||
//
|
||||
// 'from' : time filter in RFC3339 format
|
||||
// 'to' : time filter in RFC3339 format
|
||||
// ... : other fields are passed directly to the audit backend
|
||||
func (s *APIServer) searchEvents(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
||||
var err error
|
||||
to := time.Now().In(time.UTC)
|
||||
@@ -1168,8 +1170,9 @@ func (s *APIServer) searchSessionEvents(auth ClientI, w http.ResponseWriter, r *
|
||||
|
||||
// HTTP GET /:version/sessions/:id/stream?offset=x&bytes=y
|
||||
// Query parameters:
|
||||
// "offset" : bytes from the beginning
|
||||
// "bytes" : number of bytes to read (it won't return more than 512Kb)
|
||||
//
|
||||
// "offset" : bytes from the beginning
|
||||
// "bytes" : number of bytes to read (it won't return more than 512Kb)
|
||||
func (s *APIServer) getSessionChunk(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
||||
sid, err := session.ParseID(p.ByName("id"))
|
||||
if err != nil {
|
||||
@@ -1206,7 +1209,8 @@ func (s *APIServer) getSessionChunk(auth ClientI, w http.ResponseWriter, r *http
|
||||
|
||||
// HTTP GET /:version/sessions/:id/events?maxage=n
|
||||
// Query:
|
||||
// 'after' : cursor value to return events newer than N. Defaults to 0, (return all)
|
||||
//
|
||||
// 'after' : cursor value to return events newer than N. Defaults to 0, (return all)
|
||||
func (s *APIServer) getSessionEvents(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
|
||||
sid, err := session.ParseID(p.ByName("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -3790,15 +3790,15 @@ func (a *ServerWithRoles) SignDatabaseCSR(ctx context.Context, req *proto.Databa
|
||||
//
|
||||
// This certificate can be requested by:
|
||||
//
|
||||
// - Cluster administrator using "tctl auth sign --format=db" command locally
|
||||
// on the auth server to produce a certificate for configuring a self-hosted
|
||||
// database.
|
||||
// - Remote user using "tctl auth sign --format=db" command with a remote
|
||||
// proxy (e.g. Teleport Cloud), as long as they can impersonate system
|
||||
// role Db.
|
||||
// - Database service when initiating connection to a database instance to
|
||||
// produce a client certificate.
|
||||
// - Proxy service when generating mTLS files to a database
|
||||
// - Cluster administrator using "tctl auth sign --format=db" command locally
|
||||
// on the auth server to produce a certificate for configuring a self-hosted
|
||||
// database.
|
||||
// - Remote user using "tctl auth sign --format=db" command with a remote
|
||||
// proxy (e.g. Teleport Cloud), as long as they can impersonate system
|
||||
// role Db.
|
||||
// - Database service when initiating connection to a database instance to
|
||||
// produce a client certificate.
|
||||
// - Proxy service when generating mTLS files to a database
|
||||
func (a *ServerWithRoles) GenerateDatabaseCert(ctx context.Context, req *proto.DatabaseCertRequest) (*proto.DatabaseCertResponse, error) {
|
||||
// Check if the User can `create` DatabaseCertificates
|
||||
err := a.action(apidefaults.Namespace, types.KindDatabaseCertificate, types.VerbCreate)
|
||||
|
||||
+1
-1
@@ -860,7 +860,7 @@ func (c *Client) DeleteWebSession(ctx context.Context, user string, sid string)
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
// GenerateHostCert takes the public key in the Open SSH ``authorized_keys``
|
||||
// GenerateHostCert takes the public key in the Open SSH “authorized_keys“
|
||||
// plain text format, signs it using Host Certificate Authority private key and returns the
|
||||
// resulting certificate.
|
||||
func (c *Client) GenerateHostCert(
|
||||
|
||||
+10
-4
@@ -21,6 +21,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
@@ -178,6 +179,15 @@ func orgUsesExternalSSO(ctx context.Context, org string, client httpRequester) (
|
||||
var urlErr *url.Error
|
||||
|
||||
resp, err = makeHTTPGetReq(ctx, ssoURL, client)
|
||||
// Drain and close the body regardless of outcome.
|
||||
// Errors handled below.
|
||||
if resp != nil {
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
if bodyErr := resp.Body.Close(); bodyErr != nil {
|
||||
logrus.WithError(bodyErr).Error("Error closing response body.")
|
||||
}
|
||||
}
|
||||
// Handle makeHTTPGetReq errors.
|
||||
if err == nil {
|
||||
break
|
||||
} else if errors.As(err, &urlErr) && urlErr.Timeout() {
|
||||
@@ -192,10 +202,6 @@ func orgUsesExternalSSO(ctx context.Context, org string, client httpRequester) (
|
||||
// Unknown error, don't try making any more requests
|
||||
return false, trace.Wrap(err, "Unknown error trying to reach GitHub to check for organization external SSO")
|
||||
}
|
||||
err := resp.Body.Close()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("Error closing response body.")
|
||||
}
|
||||
|
||||
// "sso" page exists, org uses external SSO
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
@@ -309,7 +310,7 @@ func (m mockHTTPRequester) Do(req *http.Request) (*http.Response, error) {
|
||||
}
|
||||
|
||||
resp := new(http.Response)
|
||||
resp.Body = io.NopCloser(nil)
|
||||
resp.Body = io.NopCloser(bytes.NewReader([]byte{}))
|
||||
resp.StatusCode = m.statusCode
|
||||
|
||||
return resp, nil
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
// Package keystore provides a generic client and associated helpers for handling
|
||||
// private keys that may be backed by an HSM.
|
||||
//
|
||||
// Notes on testing
|
||||
// # Notes on testing
|
||||
//
|
||||
// Testing the Keystore package predictably requires an HSM. Testcases are
|
||||
// currently written for the "raw" KeyStore (no HSM), SoftHSMv2, YubiHSM2, and
|
||||
@@ -25,7 +25,7 @@ limitations under the License.
|
||||
// SoftHSM is enabled by default in the Teleport docker buildbox and will be
|
||||
// run in CI.
|
||||
//
|
||||
// Testing this package with SoftHSMv2
|
||||
// # Testing this package with SoftHSMv2
|
||||
//
|
||||
// To test with SoftHSMv2, you must install it (see
|
||||
// https://github.com/opendnssec/SoftHSMv2 or
|
||||
@@ -36,7 +36,7 @@ limitations under the License.
|
||||
//
|
||||
// The test will create its own config file and token, and clean up after itself.
|
||||
//
|
||||
// Testing this package with YubiHSM2
|
||||
// # Testing this package with YubiHSM2
|
||||
//
|
||||
// To test with YubiHSM2, you must:
|
||||
//
|
||||
@@ -46,7 +46,7 @@ limitations under the License.
|
||||
//
|
||||
// 3. start the connector "yubihsm-connector -d"
|
||||
//
|
||||
// 4. create a config file
|
||||
// 4. create a config file
|
||||
// connector = http://127.0.0.1:12345
|
||||
// debug
|
||||
//
|
||||
@@ -56,7 +56,7 @@ limitations under the License.
|
||||
//
|
||||
// The test will use the factory default pin of "0001password" in slot 0.
|
||||
//
|
||||
// Testing this package with AWS CloudHSM
|
||||
// # Testing this package with AWS CloudHSM
|
||||
//
|
||||
// 1. Create a CloudHSM Cluster and HSM, and activate them https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html
|
||||
//
|
||||
@@ -70,7 +70,7 @@ limitations under the License.
|
||||
//
|
||||
// 6. Run the test on the connected EC2 instance
|
||||
//
|
||||
// Testing Teleport with an HSM-backed CA
|
||||
// # Testing Teleport with an HSM-backed CA
|
||||
//
|
||||
// TBD as full support is added.
|
||||
package keystore
|
||||
|
||||
@@ -368,8 +368,8 @@ func (k *Keygen) GenerateUserCertWithoutValidation(c services.UserCertParams) ([
|
||||
// BuildPrincipals takes a hostID, nodeName, clusterName, and role and builds a list of
|
||||
// principals to insert into a certificate. This function is backward compatible with
|
||||
// older clients which means:
|
||||
// * If RoleAdmin is in the list of roles, only a single principal is returned: hostID
|
||||
// * If nodename is empty, it is not included in the list of principals.
|
||||
// - If RoleAdmin is in the list of roles, only a single principal is returned: hostID
|
||||
// - If nodename is empty, it is not included in the list of principals.
|
||||
func BuildPrincipals(hostID string, nodeName string, clusterName string, roles types.SystemRoles) []string {
|
||||
// TODO(russjones): This should probably be clusterName, but we need to
|
||||
// verify changing this won't break older clients.
|
||||
|
||||
@@ -97,13 +97,13 @@ func TestGenerateUserCert(t *testing.T) {
|
||||
|
||||
// TestBuildPrincipals makes sure that the list of principals for a host
|
||||
// certificate is correctly built.
|
||||
// * If the node has role admin, then only the host ID should be listed
|
||||
// - If the node has role admin, then only the host ID should be listed
|
||||
// in the principals field.
|
||||
// * If only a host ID is provided, don't include a empty node name
|
||||
// - If only a host ID is provided, don't include a empty node name
|
||||
// this is for backward compatibility.
|
||||
// * If both host ID and node name are given, then both should be included
|
||||
// - If both host ID and node name are given, then both should be included
|
||||
// on the certificate.
|
||||
// * If the host ID and node name are the same, only list one.
|
||||
// - If the host ID and node name are the same, only list one.
|
||||
func TestBuildPrincipals(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
+7
-8
@@ -135,8 +135,8 @@ type rotationReq struct {
|
||||
//
|
||||
// Here are the supported rotation states:
|
||||
//
|
||||
// * Standby - the cluster is in standby mode and ready to take action.
|
||||
// * In-progress - cluster CA rotation is in progress.
|
||||
// - Standby - the cluster is in standby mode and ready to take action.
|
||||
// - In-progress - cluster CA rotation is in progress.
|
||||
//
|
||||
// In-progress state is split into multiple phases and the cluster
|
||||
// can traverse between phases using supported transitions.
|
||||
@@ -183,7 +183,7 @@ type rotationReq struct {
|
||||
// reload again, but the "new" CA is discarded and is no longer trusted,
|
||||
// cluster goes back to the original state.
|
||||
//
|
||||
// Rotation modes
|
||||
// # Rotation modes
|
||||
//
|
||||
// There are two rotation modes supported - manual or automatic.
|
||||
//
|
||||
@@ -200,7 +200,6 @@ type rotationReq struct {
|
||||
//
|
||||
// It is possible to switch from automatic to manual by setting the phase
|
||||
// to the rollback phase.
|
||||
//
|
||||
func (a *Server) RotateCertAuthority(ctx context.Context, req RotateRequest) error {
|
||||
if err := req.CheckAndSetDefaults(a.clock); err != nil {
|
||||
return trace.Wrap(err)
|
||||
@@ -699,10 +698,10 @@ func (a *Server) startNewRotation(req rotationReq, ca types.CertAuthority) error
|
||||
|
||||
// updateClients swaps old and new CA key sets.
|
||||
//
|
||||
// * Old CAs continue to be trusted, but are no longer used for signing.
|
||||
// * New CAs are used for signing.
|
||||
// * Remote components will reload with new certificates used for client
|
||||
// connections.
|
||||
// - Old CAs continue to be trusted, but are no longer used for signing.
|
||||
// - New CAs are used for signing.
|
||||
// - Remote components will reload with new certificates used for client
|
||||
// connections.
|
||||
func updateClients(ca types.CertAuthority, mode string) error {
|
||||
oldActive, oldTrusted := ca.GetActiveKeys(), ca.GetAdditionalTrustedKeys()
|
||||
if err := ca.SetActiveKeys(oldTrusted); err != nil {
|
||||
|
||||
@@ -20,7 +20,6 @@ limitations under the License.
|
||||
// * Authority server itself that implements signing and acl logic
|
||||
// * HTTP server wrapper for authority server
|
||||
// * HTTP client wrapper
|
||||
//
|
||||
package auth
|
||||
|
||||
import (
|
||||
|
||||
@@ -59,15 +59,15 @@ func (l *loginWithDevices) GetMFADevices(_ context.Context, _ string, _ bool) ([
|
||||
//
|
||||
// The login flow consists of:
|
||||
//
|
||||
// 1. Client requests a CredentialAssertion (containing, among other info, a
|
||||
// challenge to be signed)
|
||||
// 2. Server runs Begin(), generates a credential assertion.
|
||||
// 3. Client validates the assertion, performs a user presence test (usually by
|
||||
// asking the user to touch a secure token), and replies with
|
||||
// CredentialAssertionResponse (containing the signed challenge)
|
||||
// 4. Server runs Finish()
|
||||
// 5. If all server-side checks are successful, then login/authentication is
|
||||
// complete.
|
||||
// 1. Client requests a CredentialAssertion (containing, among other info, a
|
||||
// challenge to be signed)
|
||||
// 2. Server runs Begin(), generates a credential assertion.
|
||||
// 3. Client validates the assertion, performs a user presence test (usually by
|
||||
// asking the user to touch a secure token), and replies with
|
||||
// CredentialAssertionResponse (containing the signed challenge)
|
||||
// 4. Server runs Finish()
|
||||
// 5. If all server-side checks are successful, then login/authentication is
|
||||
// complete.
|
||||
type LoginFlow struct {
|
||||
U2F *types.U2F
|
||||
Webauthn *types.Webauthn
|
||||
|
||||
@@ -103,16 +103,16 @@ func sessionDataKey(user, sessionID string) string {
|
||||
//
|
||||
// Registration consists of:
|
||||
//
|
||||
// 1. Client requests a CredentialCreation (containing a challenge and various
|
||||
// settings that may constrain allowed authenticators).
|
||||
// 2. Server runs Begin(), generates a credential creation.
|
||||
// 3. Client validates the credential creation, performs a user presence test
|
||||
// (usually by asking the user to touch a secure token), and replies with a
|
||||
// CredentialCreationResponse (containing the signed challenge and
|
||||
// information about the credential and authenticator)
|
||||
// 4. Server runs Finish()
|
||||
// 5. If all server-side checks are successful, then registration is complete
|
||||
// and the authenticator may now be used to login.
|
||||
// 1. Client requests a CredentialCreation (containing a challenge and various
|
||||
// settings that may constrain allowed authenticators).
|
||||
// 2. Server runs Begin(), generates a credential creation.
|
||||
// 3. Client validates the credential creation, performs a user presence test
|
||||
// (usually by asking the user to touch a secure token), and replies with a
|
||||
// CredentialCreationResponse (containing the signed challenge and
|
||||
// information about the credential and authenticator)
|
||||
// 4. Server runs Finish()
|
||||
// 5. If all server-side checks are successful, then registration is complete
|
||||
// and the authenticator may now be used to login.
|
||||
type RegistrationFlow struct {
|
||||
Webauthn *types.Webauthn
|
||||
Identity RegistrationIdentity
|
||||
|
||||
@@ -122,7 +122,6 @@ type Batch interface {
|
||||
// lease, err := backend.Create(ctx, item)
|
||||
// expires := time.Now().Add(20 * time.Second)
|
||||
// err = backend.KeepAlive(ctx, lease, expires)
|
||||
//
|
||||
type Lease struct {
|
||||
// Key is an object representing lease
|
||||
Key []byte
|
||||
|
||||
+1
-1
@@ -18,6 +18,6 @@ limitations under the License.
|
||||
// backend package allows for pluggable back-ends for secrets storage.
|
||||
// To implement a new storage back-end you have to supply an object
|
||||
// which:
|
||||
// - implements backend.Backend interface
|
||||
// - implements backend.Backend interface
|
||||
// - implements backend.NewFunc function
|
||||
package backend
|
||||
|
||||
@@ -21,7 +21,7 @@ auth server. Originally contributed by https://github.com/apestel
|
||||
|
||||
limitations:
|
||||
|
||||
* Paging is not implemented, hence all range operations are limited
|
||||
to 1MB result set
|
||||
- Paging is not implemented, hence all range operations are limited
|
||||
to 1MB result set
|
||||
*/
|
||||
package dynamo
|
||||
|
||||
@@ -18,6 +18,5 @@ for Teleport auth service, similar to DynamoDB backend.
|
||||
|
||||
firestore package implements the FirestoreBackend storage back-end for the
|
||||
auth server. Originally contributed by https://github.com/joshdurbin
|
||||
|
||||
*/
|
||||
package firestore
|
||||
|
||||
@@ -53,7 +53,6 @@ func TestMain(m *testing.M) {
|
||||
// to verify backwards compatibility. Gogoproto is incompatible with ApiV2 protoc-gen-go code.
|
||||
//
|
||||
// Track the issue here: https://github.com/gogo/protobuf/issues/678
|
||||
//
|
||||
func TestMarshal(t *testing.T) {
|
||||
meta := adminpb.IndexOperationMetadata{}
|
||||
data, err := proto.Marshal(&meta)
|
||||
|
||||
+11
-11
@@ -17,18 +17,19 @@ limitations under the License.
|
||||
/*
|
||||
Package postgres implements a SQL backend for PostgreSQL and CockroachDB.
|
||||
|
||||
Schema
|
||||
# Schema
|
||||
|
||||
The database schema consists of three tables: item, lease, and event.
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ item │ │ lease │ │ event │
|
||||
├──────────┤ ├──────────┤ ├──────────┤
|
||||
│* key │ │* key │ │* eventid │
|
||||
│* id │ │ id │ │ created │
|
||||
│ value │ │ expires │ │ key │
|
||||
│ │ │ │ │ id │
|
||||
│ │ │ │ │ type │
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ item │ │ lease │ │ event │
|
||||
├──────────┤ ├──────────┤ ├──────────┤
|
||||
│* key │ │* key │ │* eventid │
|
||||
│* id │ │ id │ │ created │
|
||||
│ value │ │ expires │ │ key │
|
||||
│ │ │ │ │ id │
|
||||
│ │ │ │ │ type │
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
|
||||
The item table contains the backend item's value and is insert-only. The table
|
||||
supports multiple items per key. Updates to an item's value creates a new
|
||||
@@ -44,6 +45,5 @@ type represents the value of types.OpType.
|
||||
|
||||
The design allows for items to be updated before an event for previous item has
|
||||
been emitted without duplicating storage for value.
|
||||
|
||||
*/
|
||||
package postgres
|
||||
|
||||
@@ -37,7 +37,8 @@ func getMigration(version int) string {
|
||||
//
|
||||
// Keys are stored as BYTEA to avoid collation ordering.
|
||||
// When debugging, convert the key to a readable value using:
|
||||
// SELECT encode(key, 'escape') FROM lease;
|
||||
//
|
||||
// SELECT encode(key, 'escape') FROM lease;
|
||||
const migrateV1 = `
|
||||
CREATE TABLE item (
|
||||
key BYTEA NOT NULL,
|
||||
|
||||
@@ -24,12 +24,10 @@ an interface to create transactions with cancellation through a Tx interface.
|
||||
|
||||
Driver -> DB -> Tx
|
||||
|
||||
Testing
|
||||
# Testing
|
||||
|
||||
Test a Driver implementation using the TestDriver package function. The test
|
||||
will configure the driver for use with a test backend and execute the backend
|
||||
test suite. See driver implementations for details about configuring tests.
|
||||
|
||||
|
||||
*/
|
||||
package sqlbk
|
||||
|
||||
Vendored
+16
-16
@@ -862,23 +862,23 @@ func (c *Cache) notify(ctx context.Context, event Event) {
|
||||
// and consistently ordered thanks to Raft. Unfortunately, DynamoDB
|
||||
// does not provide such a mechanism for its event system, so
|
||||
// some tradeoffs have to be made:
|
||||
// a. We assume that events are ordered in regards to the
|
||||
// individual key operations which is the guarantees both Etcd and DynamoDB
|
||||
// provide.
|
||||
// b. Thanks to the init event sent by the server on a successful connect,
|
||||
// and guarantees 1 and 2a, client assumes that once it connects and receives an event,
|
||||
// it will not miss any events, however it can receive stale events.
|
||||
// Event could be stale, if it relates to a change that happened before
|
||||
// the version read by client from the database, for example,
|
||||
// given the event stream: 1. Update a=1 2. Delete a 3. Put a = 2
|
||||
// Client could have subscribed before event 1 happened,
|
||||
// read the value a=2 and then received events 1 and 2 and 3.
|
||||
// The cache will replay all events 1, 2 and 3 and end up in the correct
|
||||
// state 3. If we had a consistent revision number, we could
|
||||
// have skipped 1 and 2, but in the absence of such mechanism in Dynamo
|
||||
// we assume that this cache will eventually end up in a correct state
|
||||
// potentially lagging behind the state of the database.
|
||||
//
|
||||
// a. We assume that events are ordered in regards to the
|
||||
// individual key operations which is the guarantees both Etcd and DynamoDB
|
||||
// provide.
|
||||
// b. Thanks to the init event sent by the server on a successful connect,
|
||||
// and guarantees 1 and 2a, client assumes that once it connects and receives an event,
|
||||
// it will not miss any events, however it can receive stale events.
|
||||
// Event could be stale, if it relates to a change that happened before
|
||||
// the version read by client from the database, for example,
|
||||
// given the event stream: 1. Update a=1 2. Delete a 3. Put a = 2
|
||||
// Client could have subscribed before event 1 happened,
|
||||
// read the value a=2 and then received events 1 and 2 and 3.
|
||||
// The cache will replay all events 1, 2 and 3 and end up in the correct
|
||||
// state 3. If we had a consistent revision number, we could
|
||||
// have skipped 1 and 2, but in the absence of such mechanism in Dynamo
|
||||
// we assume that this cache will eventually end up in a correct state
|
||||
// potentially lagging behind the state of the database.
|
||||
func (c *Cache) fetchAndWatch(ctx context.Context, retry utils.Retry, timer *time.Timer) error {
|
||||
watcher, err := c.Events.NewWatcher(c.ctx, types.Watch{
|
||||
QueueSize: c.QueueSize,
|
||||
|
||||
@@ -341,7 +341,8 @@ type standaloneBundle struct {
|
||||
}
|
||||
|
||||
// TODO(codingllama): Consider refactoring newStandaloneTeleport into a public
|
||||
// function and reusing in other places.
|
||||
//
|
||||
// function and reusing in other places.
|
||||
func newStandaloneTeleport(t *testing.T, clock clockwork.Clock) *standaloneBundle {
|
||||
randomAddr := utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ type NodeClient struct {
|
||||
|
||||
// GetSites returns list of the "sites" (AKA teleport clusters) connected to the proxy
|
||||
// Each site is returned as an instance of its auth server
|
||||
//
|
||||
func (proxy *ProxyClient) GetSites(ctx context.Context) ([]types.Site, error) {
|
||||
ctx, span := proxy.Tracer.Start(
|
||||
ctx,
|
||||
|
||||
@@ -72,9 +72,10 @@ func NewSSHConnectionTester(cfg SSHConnectionTesterConfig) (*SSHConnectionTester
|
||||
}
|
||||
|
||||
// TestConnection tests an SSH Connection to the target Node using
|
||||
// - the provided client
|
||||
// - resource name
|
||||
// - principal / linux user
|
||||
// - the provided client
|
||||
// - resource name
|
||||
// - principal / linux user
|
||||
//
|
||||
// A new ConnectionDiagnostic is created and used to store the traces as it goes through the checkpoints
|
||||
// To set up the SSH client, it will generate a new cert and inject the ConnectionDiagnosticID
|
||||
// - add a trace of whether the SSH Node was reachable
|
||||
|
||||
@@ -67,18 +67,18 @@ func LoadFromPath(path string) (*ServiceFile, error) {
|
||||
// The profile goes into a separate section with the name equal to the
|
||||
// name of the database that user is logged into and looks like this:
|
||||
//
|
||||
// [postgres]
|
||||
// host=proxy.example.com
|
||||
// port=3080
|
||||
// sslmode=verify-full
|
||||
// sslrootcert=/home/user/.tsh/keys/proxy.example.com/certs.pem
|
||||
// sslcert=/home/user/.tsh/keys/proxy.example.com/alice-db/root/aurora-x509.pem
|
||||
// sslkey=/home/user/.tsh/keys/proxy.example.com/user
|
||||
// [postgres]
|
||||
// host=proxy.example.com
|
||||
// port=3080
|
||||
// sslmode=verify-full
|
||||
// sslrootcert=/home/user/.tsh/keys/proxy.example.com/certs.pem
|
||||
// sslcert=/home/user/.tsh/keys/proxy.example.com/alice-db/root/aurora-x509.pem
|
||||
// sslkey=/home/user/.tsh/keys/proxy.example.com/user
|
||||
//
|
||||
// With the profile like this, a user can refer to it using "service" psql
|
||||
// parameter:
|
||||
//
|
||||
// $ psql "service=postgres <other parameters>"
|
||||
// $ psql "service=postgres <other parameters>"
|
||||
func (s *ServiceFile) Upsert(profile profile.ConnectProfile) error {
|
||||
section := s.iniFile.Section(profile.Name)
|
||||
if section != nil {
|
||||
|
||||
@@ -18,10 +18,12 @@ limitations under the License.
|
||||
// that combine connection parameters for a particular database.
|
||||
//
|
||||
// For Postgres it's the connection service file:
|
||||
// https://www.postgresql.org/docs/current/libpq-pgservice.html
|
||||
//
|
||||
// https://www.postgresql.org/docs/current/libpq-pgservice.html
|
||||
//
|
||||
// For MySQL it's the option file:
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/option-files.html
|
||||
//
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/option-files.html
|
||||
package db
|
||||
|
||||
import (
|
||||
|
||||
@@ -62,11 +62,11 @@ type Reader struct {
|
||||
// NewReader creates a new Reader to catch escape sequences from 'in'.
|
||||
//
|
||||
// Two sequences are supported:
|
||||
// - "~?": prints help text to 'out' listing supported sequences
|
||||
// - "~.": disconnect stops any future reads from in; after this sequence,
|
||||
// callers can still read any unread data up to this sequence from Reader but
|
||||
// all future Read calls will return ErrDisconnect; onDisconnect will also be
|
||||
// called with ErrDisconnect immediately
|
||||
// - "~?": prints help text to 'out' listing supported sequences
|
||||
// - "~.": disconnect stops any future reads from in; after this sequence,
|
||||
// callers can still read any unread data up to this sequence from Reader but
|
||||
// all future Read calls will return ErrDisconnect; onDisconnect will also be
|
||||
// called with ErrDisconnect immediately
|
||||
//
|
||||
// NewReader starts consuming 'in' immediately in the background. This allows
|
||||
// Reader to detect sequences without the caller actively calling Read (such as
|
||||
|
||||
@@ -90,11 +90,11 @@ type WebClient struct {
|
||||
|
||||
// PostJSONWithFallback serializes an object to JSON and attempts to execute a POST
|
||||
// using HTTPS, and then fall back to plain HTTP under certain, very specific circumstances.
|
||||
// * The caller must specifically allow it via the allowHTTPFallback parameter, and
|
||||
// * The target host must resolve to the loopback address.
|
||||
// - The caller must specifically allow it via the allowHTTPFallback parameter, and
|
||||
// - The target host must resolve to the loopback address.
|
||||
//
|
||||
// If these conditions are not met, then the plain-HTTP fallback is not allowed,
|
||||
// and a the HTTPS failure will be considered final.
|
||||
//
|
||||
func (w *WebClient) PostJSONWithFallback(ctx context.Context, endpoint string, val interface{}, allowHTTPFallback bool) (*roundtrip.Response, error) {
|
||||
// First try HTTPS and see how that goes
|
||||
log.Debugf("Attempting %s", endpoint)
|
||||
|
||||
@@ -36,7 +36,8 @@ func NewInMemoryConfigWriter() *InMemoryConfigWriter {
|
||||
}
|
||||
|
||||
// InMemoryConfigWriter is a basic virtual file system abstraction that writes into memory
|
||||
// instead of writing to a more persistent storage.
|
||||
//
|
||||
// instead of writing to a more persistent storage.
|
||||
type InMemoryConfigWriter struct {
|
||||
mux *sync.RWMutex
|
||||
files map[string]*utils.InMemoryFile
|
||||
|
||||
@@ -333,7 +333,6 @@ func (k *Key) clientCertPool(clusters ...string) (*x509.CertPool, error) {
|
||||
//
|
||||
// The config is set up to authenticate to proxy with the first available principal
|
||||
// and ( if keyStore != nil ) trust local SSH CAs without asking for public keys.
|
||||
//
|
||||
func (k *Key) ProxyClientSSHConfig(keyStore sshKnowHostGetter, host string) (*ssh.ClientConfig, error) {
|
||||
sshCert, err := k.SSHCert()
|
||||
if err != nil {
|
||||
|
||||
@@ -83,12 +83,12 @@ func makeSuite(t *testing.T) *KeyAgentTestSuite {
|
||||
}
|
||||
|
||||
// TestAddKey ensures correct adding of ssh keys. This test checks the following:
|
||||
// * When adding a key it's written to disk.
|
||||
// * When we add a key, it's added to both the teleport ssh agent as well
|
||||
// - When adding a key it's written to disk.
|
||||
// - When we add a key, it's added to both the teleport ssh agent as well
|
||||
// as the system ssh agent.
|
||||
// * When we add a key, both the certificate and private key are added into
|
||||
// - When we add a key, both the certificate and private key are added into
|
||||
// the both the teleport ssh agent and the system ssh agent.
|
||||
// * When we add a key, it's tagged with a comment that indicates that it's
|
||||
// - When we add a key, it's tagged with a comment that indicates that it's
|
||||
// a teleport key with the teleport username.
|
||||
func TestAddKey(t *testing.T) {
|
||||
s := makeSuite(t)
|
||||
@@ -157,8 +157,8 @@ func TestAddKey(t *testing.T) {
|
||||
|
||||
// TestLoadKey ensures correct loading of a key into an agent. This test
|
||||
// checks the following:
|
||||
// * Loading a key multiple times overwrites the same key.
|
||||
// * The key is correctly loaded into the agent. This is tested by having
|
||||
// - Loading a key multiple times overwrites the same key.
|
||||
// - The key is correctly loaded into the agent. This is tested by having
|
||||
// the agent sign data that is then verified using the public key
|
||||
// directly.
|
||||
func TestLoadKey(t *testing.T) {
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -8,7 +8,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -16,8 +16,8 @@ limitations under the License.
|
||||
|
||||
// Package config provides facilities for configuring Teleport daemons
|
||||
// including
|
||||
// - parsing YAML configuration
|
||||
// - parsing CLI flags
|
||||
// - parsing YAML configuration
|
||||
// - parsing CLI flags
|
||||
package config
|
||||
|
||||
import (
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
+4
-4
@@ -29,12 +29,12 @@ type Event struct {
|
||||
// There is no strict algorithm for picking an event code, however existing
|
||||
// event codes are currently loosely categorized as follows:
|
||||
//
|
||||
// * Teleport event codes start with "T" and belong in this const block.
|
||||
// - Teleport event codes start with "T" and belong in this const block.
|
||||
//
|
||||
// * Related events are grouped starting with the same number.
|
||||
// eg: All user related events are grouped under 1xxx.
|
||||
// - Related events are grouped starting with the same number.
|
||||
// eg: All user related events are grouped under 1xxx.
|
||||
//
|
||||
// * Suffix code with one of these letters: I (info), W (warn), E (error).
|
||||
// - Suffix code with one of these letters: I (info), W (warn), E (error).
|
||||
const (
|
||||
// UserLocalLoginCode is the successful local user login event code.
|
||||
UserLocalLoginCode = "T1000I"
|
||||
|
||||
+19
-18
@@ -27,11 +27,12 @@ and session log events like session.start.
|
||||
Example audit log event:
|
||||
|
||||
{"addr.local":"172.10.1.20:3022",
|
||||
"addr.remote":"172.10.1.254:58866",
|
||||
"event":"session.start",
|
||||
"login":"root",
|
||||
"user":"[email protected]"
|
||||
}
|
||||
|
||||
"addr.remote":"172.10.1.254:58866",
|
||||
"event":"session.start",
|
||||
"login":"root",
|
||||
"user":"[email protected]"
|
||||
}
|
||||
|
||||
Session Logs
|
||||
------------
|
||||
@@ -40,15 +41,15 @@ Session logs are a series of events and recorded SSH interactive session playbac
|
||||
|
||||
Example session log event:
|
||||
|
||||
{
|
||||
"time":"2018-01-04T02:12:40.245Z",
|
||||
"event":"print",
|
||||
"bytes":936,
|
||||
"ms":40962,
|
||||
"offset":16842,
|
||||
"ei":31,
|
||||
"ci":29
|
||||
}
|
||||
{
|
||||
"time":"2018-01-04T02:12:40.245Z",
|
||||
"event":"print",
|
||||
"bytes":936,
|
||||
"ms":40962,
|
||||
"offset":16842,
|
||||
"ei":31,
|
||||
"ci":29
|
||||
}
|
||||
|
||||
Print event fields
|
||||
------------------
|
||||
@@ -124,8 +125,8 @@ Files:
|
||||
/var/lib/teleport/log/<auth-server-id>/<session-id>-<first-chunk-in-file-offset>.chunks
|
||||
|
||||
Where:
|
||||
- .events (same events as in the main log, but related to the session)
|
||||
- .chunks (recorded session bytes: PTY IO)
|
||||
- .events (same events as in the main log, but related to the session)
|
||||
- .chunks (recorded session bytes: PTY IO)
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -159,7 +160,8 @@ emitted by print event with chunk index 0
|
||||
**Multiple Auth Servers**
|
||||
|
||||
In High Availability mode scenario, multiple auth servers will be
|
||||
deployed behind a load balancer.
|
||||
|
||||
deployed behind a load balancer.
|
||||
|
||||
Any auth server can go down during session and clients will retry the delivery
|
||||
to the other auth server.
|
||||
@@ -217,6 +219,5 @@ Log Search and Playback
|
||||
|
||||
Log search and playback is aware of multiple auth servers, merges
|
||||
indexes, event streams stored on multiple auth servers.
|
||||
|
||||
*/
|
||||
package events
|
||||
|
||||
@@ -46,7 +46,6 @@ import (
|
||||
// Data race detector slows down the test significantly (10x+),
|
||||
// that is why the test is skipped when tests are running with
|
||||
// `go test -race` flag or `go test -short` flag
|
||||
//
|
||||
func TestChaosUpload(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping chaos test in short mode.")
|
||||
|
||||
@@ -18,6 +18,5 @@ for Teleport event storage.
|
||||
|
||||
firestoreevents package implements the Log storage back-end for the
|
||||
auth server. Originally contributed by https://github.com/joshdurbin
|
||||
|
||||
*/
|
||||
package firestoreevents
|
||||
|
||||
@@ -18,6 +18,5 @@ for Teleport session recording persistence.
|
||||
|
||||
gcssessions package implements the Handler session recording storage for
|
||||
auth server. Originally contributed by https://github.com/joshdurbin
|
||||
|
||||
*/
|
||||
package gcssessions
|
||||
|
||||
@@ -225,7 +225,6 @@ func (cfg *ProtoStreamConfig) CheckAndSetDefaults() error {
|
||||
// The individual session stream is represented by continuous globally
|
||||
// ordered sequence of events serialized to binary protobuf format.
|
||||
//
|
||||
//
|
||||
// The stream is split into ordered slices of gzipped audit events.
|
||||
//
|
||||
// Each slice is composed of three parts:
|
||||
@@ -247,7 +246,6 @@ func (cfg *ProtoStreamConfig) CheckAndSetDefaults() error {
|
||||
//
|
||||
// This design allows the streamer to upload slices using S3-compatible APIs
|
||||
// in parallel without buffering to disk.
|
||||
//
|
||||
func NewProtoStream(cfg ProtoStreamConfig) (*ProtoStream, error) {
|
||||
if err := cfg.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
||||
@@ -95,7 +95,6 @@ func BenchmarkStore(b *testing.B) {
|
||||
// TestStoreAccess verifies the two most important properties of the store:
|
||||
// 1. Handles are loadable by ID.
|
||||
// 2. When multiple handles have the same ID, loads are distributed across them.
|
||||
//
|
||||
func TestStoreAccess(t *testing.T) {
|
||||
store := NewStore()
|
||||
|
||||
|
||||
@@ -66,10 +66,10 @@ type ImpersonationPermissionsChecker func(ctx context.Context, clusterName strin
|
||||
// getKubeCreds fetches the kubernetes API credentials.
|
||||
//
|
||||
// There are 2 possible sources of credentials:
|
||||
// - pod service account credentials: files in hardcoded paths when running
|
||||
// inside of a k8s pod; this is used when kubeClusterName is set
|
||||
// - kubeconfig: a file with a set of k8s endpoints and credentials mapped to
|
||||
// them this is used when kubeconfigPath is set
|
||||
// - pod service account credentials: files in hardcoded paths when running
|
||||
// inside of a k8s pod; this is used when kubeClusterName is set
|
||||
// - kubeconfig: a file with a set of k8s endpoints and credentials mapped to
|
||||
// them this is used when kubeconfigPath is set
|
||||
//
|
||||
// serviceType changes the loading behavior:
|
||||
// - LegacyProxyService:
|
||||
@@ -77,8 +77,10 @@ type ImpersonationPermissionsChecker func(ctx context.Context, clusterName strin
|
||||
// returned map key matches tpClusterName
|
||||
// - if no credentials are loaded, no error is returned
|
||||
// - permission self-test failures are only logged
|
||||
//
|
||||
// - ProxyService:
|
||||
// - no credentials are loaded and no error is returned
|
||||
//
|
||||
// - KubeService:
|
||||
// - if loading from kubeconfig, all contexts are returned
|
||||
// - if no credentials are loaded, returns an error
|
||||
|
||||
@@ -2009,6 +2009,7 @@ func (f *Forwarder) requestCertificate(ctx authContext) (*tls.Config, error) {
|
||||
RootCAs: pool,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
//nolint:staticcheck // Keep BuildNameToCertificate to avoid changes in legacy behavior.
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
|
||||
return tlsConfig, nil
|
||||
|
||||
@@ -768,7 +768,7 @@ func TestNewClusterSessionRemote(t *testing.T) {
|
||||
// getClientCreds returns the cached version of the client tlsConfig.
|
||||
require.NotNil(t, f.getClientCreds(authCtx))
|
||||
require.NotSame(t, f.getClientCreds(authCtx), sess.tlsConfig)
|
||||
//lint:ignore SA1019 there's no non-deprecated public API for testing the contents of the RootCAs pool
|
||||
//nolint:staticcheck // SA1019 there's no non-deprecated public API for testing the contents of the RootCAs pool
|
||||
require.Equal(t, [][]byte{f.cfg.AuthClient.(*mockCSRClient).ca.Cert.RawSubject}, sess.tlsConfig.RootCAs.Subjects())
|
||||
require.Equal(t, 1, f.clientCredentials.Len())
|
||||
}
|
||||
@@ -821,7 +821,7 @@ func TestNewClusterSessionDirect(t *testing.T) {
|
||||
|
||||
// Make sure newClusterSession obtained a new client cert instead of using f.creds.
|
||||
require.Equal(t, f.cfg.AuthClient.(*mockCSRClient).lastCert.Raw, sess.tlsConfig.Certificates[0].Certificate[0])
|
||||
//lint:ignore SA1019 there's no non-deprecated public API for testing the contents of the RootCAs pool
|
||||
//nolint:staticcheck // SA1019 there's no non-deprecated public API for testing the contents of the RootCAs pool
|
||||
require.Equal(t, [][]byte{f.cfg.AuthClient.(*mockCSRClient).ca.Cert.RawSubject}, sess.tlsConfig.RootCAs.Subjects())
|
||||
// Make sure that sess.tlsConfig was cloned from the value we store in the cache.
|
||||
// This is important because each connection must refer to a different memory address so it can be manipulated to enable/disable http2
|
||||
|
||||
@@ -100,9 +100,13 @@ func TestPingPong(t *testing.T) {
|
||||
defer server.Close()
|
||||
|
||||
url := "ws" + strings.TrimPrefix(server.URL, "http")
|
||||
ws, _, err := websocket.DefaultDialer.Dial(url, nil)
|
||||
ws, resp, err := websocket.DefaultDialer.Dial(url, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Always drain/close the body.
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
|
||||
go func() {
|
||||
defer ws.Close()
|
||||
errCh <- runClient(ws)
|
||||
|
||||
@@ -137,7 +137,6 @@ func GetKubeConfig(configPath string, allConfigEntries bool, clusterName string)
|
||||
//
|
||||
// It is hex encoded to allow wildcard matching to work. In DNS wildcard match
|
||||
// include only one '.'
|
||||
//
|
||||
func EncodeClusterName(clusterName string) string {
|
||||
// k is to avoid first letter to be a number
|
||||
return "k" + hex.EncodeToString([]byte(clusterName))
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
+10
-11
@@ -38,19 +38,18 @@ type TestModules struct {
|
||||
// and reverts the change in the test cleanup function.
|
||||
// It must not be used in parallel tests.
|
||||
//
|
||||
// func TestWithFakeModules(t *testing.T) {
|
||||
// modules.SetTestModules(t, &modules.TestModules{
|
||||
// TestBuildType: modules.BuildEnterprise,
|
||||
// TestFeatures: modules.Features{
|
||||
// Cloud: true,
|
||||
// },
|
||||
// })
|
||||
// func TestWithFakeModules(t *testing.T) {
|
||||
// modules.SetTestModules(t, &modules.TestModules{
|
||||
// TestBuildType: modules.BuildEnterprise,
|
||||
// TestFeatures: modules.Features{
|
||||
// Cloud: true,
|
||||
// },
|
||||
// })
|
||||
//
|
||||
// // test implementation
|
||||
//
|
||||
// // cleanup will revert module changes after test completes
|
||||
// }
|
||||
// // test implementation
|
||||
//
|
||||
// // cleanup will revert module changes after test completes
|
||||
// }
|
||||
func SetTestModules(t *testing.T, testModules *TestModules) {
|
||||
defaultModules := GetModules()
|
||||
t.Cleanup(func() { SetModules(defaultModules) })
|
||||
|
||||
@@ -20,7 +20,6 @@ limitations under the License.
|
||||
// mux, _ := multiplexer.New(Config{Listener: listener})
|
||||
// mux.SSH() // returns listener getting SSH connections
|
||||
// mux.TLS() // returns listener getting TLS connections
|
||||
//
|
||||
package multiplexer
|
||||
|
||||
import (
|
||||
|
||||
@@ -27,9 +27,9 @@ import (
|
||||
)
|
||||
|
||||
// RegisterPrometheusCollectors is a wrapper around prometheus.Register that
|
||||
// - ignores equal or re-registered collectors
|
||||
// - returns an error if a collector does not fulfill the consistency and
|
||||
// uniqueness criteria
|
||||
// - ignores equal or re-registered collectors
|
||||
// - returns an error if a collector does not fulfill the consistency and
|
||||
// uniqueness criteria
|
||||
func RegisterPrometheusCollectors(collectors ...prometheus.Collector) error {
|
||||
var errs []error
|
||||
for _, c := range collectors {
|
||||
|
||||
+3
-3
@@ -402,9 +402,9 @@ func (p *PAM) Close() error {
|
||||
// variables and it is the responsibility of the caller to free that memory.
|
||||
// From http://man7.org/linux/man-pages/man3/pam_getenvlist.3.html:
|
||||
//
|
||||
// It should be noted that this memory will never be free()'d by libpam.
|
||||
// Once obtained by a call to pam_getenvlist, it is the responsibility
|
||||
// of the calling application to free() this memory.
|
||||
// It should be noted that this memory will never be free()'d by libpam.
|
||||
// Once obtained by a call to pam_getenvlist, it is the responsibility
|
||||
// of the calling application to free() this memory.
|
||||
func (p *PAM) Environment() []string {
|
||||
// Get list of additional environment variables requested from PAM.
|
||||
pam_envlist := C._pam_getenvlist(pamHandle, p.pamh)
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
+28
-22
@@ -16,28 +16,30 @@ limitations under the License.
|
||||
|
||||
/*
|
||||
Package reversetunnel provides interfaces for accessing remote clusters
|
||||
via reverse tunnels and directly.
|
||||
|
||||
via reverse tunnels and directly.
|
||||
|
||||
Reverse Tunnels
|
||||
|
||||
Proxy server Proxy agent
|
||||
Reverse tunnel
|
||||
+----------+ +---------+
|
||||
| <----------------------+ |
|
||||
| | | |
|
||||
Proxy server Proxy agent
|
||||
Reverse tunnel
|
||||
+----------+ +---------+
|
||||
| <----------------------+ |
|
||||
| | | |
|
||||
|
||||
+-----+----------+ +---------+-----+
|
||||
| | | |
|
||||
| | | |
|
||||
+----------------+ +---------------+
|
||||
Proxy Cluster "A" Proxy Cluster "B"
|
||||
|
||||
Proxy Cluster "A" Proxy Cluster "B"
|
||||
|
||||
Reverse tunnel is established from a cluster "B" Proxy
|
||||
to the a cluster "A" proxy, and clients of the cluster "A"
|
||||
can access servers of the cluster "B" via reverse tunnel connection,
|
||||
even if the cluster "B" is behind the firewall.
|
||||
|
||||
Multiple Proxies and Revese Tunnels
|
||||
# Multiple Proxies and Revese Tunnels
|
||||
|
||||
With multiple proxies behind the load balancer,
|
||||
proxy agents will eventually discover and establish connections to all
|
||||
@@ -47,24 +49,28 @@ proxies in cluster.
|
||||
* Proxy 1 starts sending information about all available proxies
|
||||
to the the Proxy Agent . This process is called "sending discovery request".
|
||||
|
||||
|
||||
+----------+
|
||||
| <--------+
|
||||
| | |
|
||||
+----------+ | +-----------+ +----------+
|
||||
Proxy 1 +-------------------------------+ |
|
||||
| | | |
|
||||
+-----------+ +----------+
|
||||
Load Balancer Proxy Agent
|
||||
|
||||
Proxy 1 +-------------------------------+ |
|
||||
| | | |
|
||||
+-----------+ +----------+
|
||||
Load Balancer Proxy Agent
|
||||
|
||||
+----------+
|
||||
| |
|
||||
| |
|
||||
+----------+
|
||||
Proxy 2
|
||||
|
||||
Proxy 2
|
||||
|
||||
* Agent will use the discovery request to establish new connections
|
||||
and check if it has connected and "discovered" all the proxies specified
|
||||
in the discovery request.
|
||||
|
||||
in the discovery request.
|
||||
|
||||
* Assuming that load balancer uses fair load balancing algorithm,
|
||||
agent will eventually discover and connect back to all the proxies.
|
||||
|
||||
@@ -72,17 +78,17 @@ agent will eventually discover and connect back to all the proxies.
|
||||
| <--------+
|
||||
| | |
|
||||
+----------+ | +-----------+ +----------+
|
||||
Proxy 1 +-------------------------------+ |
|
||||
| | | | |
|
||||
| +-----------+ +----------+
|
||||
| Load Balancer Proxy Agent
|
||||
|
||||
Proxy 1 +-------------------------------+ |
|
||||
| | | | |
|
||||
| +-----------+ +----------+
|
||||
| Load Balancer Proxy Agent
|
||||
|
||||
+----------+ |
|
||||
| <--------+
|
||||
| |
|
||||
+----------+
|
||||
Proxy 2
|
||||
|
||||
|
||||
|
||||
Proxy 2
|
||||
*/
|
||||
package reversetunnel
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -2560,6 +2560,7 @@ func (process *TeleportProcess) initMetricsService() error {
|
||||
|
||||
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
tlsConfig.ClientCAs = pool
|
||||
//nolint:staticcheck // Keep BuildNameToCertificate to avoid changes in legacy behavior.
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
|
||||
listener = tls.NewListener(listener, tlsConfig)
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -210,13 +210,13 @@ type accessChecker struct {
|
||||
// NewAccessChecker returns a new AccessChecker which can be used to check
|
||||
// access to resources.
|
||||
// Args:
|
||||
// - `info *AccessInfo` should hold the roles, traits, and allowed resource IDs
|
||||
// for the identity.
|
||||
// - `localCluster string` should be the name of the local cluster in which
|
||||
// access will be checked. You cannot check for access to resources in remote
|
||||
// clusters.
|
||||
// - `access RoleGetter` should be a RoleGetter which will be used to fetch the
|
||||
// full RoleSet
|
||||
// - `info *AccessInfo` should hold the roles, traits, and allowed resource IDs
|
||||
// for the identity.
|
||||
// - `localCluster string` should be the name of the local cluster in which
|
||||
// access will be checked. You cannot check for access to resources in remote
|
||||
// clusters.
|
||||
// - `access RoleGetter` should be a RoleGetter which will be used to fetch the
|
||||
// full RoleSet
|
||||
func NewAccessChecker(info *AccessInfo, localCluster string, access RoleGetter) (AccessChecker, error) {
|
||||
roleSet, err := FetchRoles(info.Roles, access, info.Traits)
|
||||
if err != nil {
|
||||
|
||||
@@ -1314,16 +1314,16 @@ func MarshalAccessRequest(accessRequest types.AccessRequest, opts ...MarshalOpti
|
||||
}
|
||||
|
||||
// pruneResourceRequestRoles takes an access request and does one of two things:
|
||||
// 1. If it is a role request, returns it unchanged.
|
||||
// 2. If it is a resource request, all available `search_as_roles` for the user
|
||||
// should have been populated on the request by `ValidateAccessReqeustForUser`.
|
||||
// This function will attempt to prune these roles to a minimal necessary set
|
||||
// based on the following rules:
|
||||
// - If a role does not grant access to any resources in the set, it is pruned.
|
||||
// - If the request includes a LoginHint, access to a node with that login
|
||||
// should be satisfied by exactly 1 role. The first such role will be
|
||||
// requested, all others will be pruned unless they are necessary to access
|
||||
// a different resource in the set.
|
||||
// 1. If it is a role request, returns it unchanged.
|
||||
// 2. If it is a resource request, all available `search_as_roles` for the user
|
||||
// should have been populated on the request by `ValidateAccessReqeustForUser`.
|
||||
// This function will attempt to prune these roles to a minimal necessary set
|
||||
// based on the following rules:
|
||||
// - If a role does not grant access to any resources in the set, it is pruned.
|
||||
// - If the request includes a LoginHint, access to a node with that login
|
||||
// should be satisfied by exactly 1 role. The first such role will be
|
||||
// requested, all others will be pruned unless they are necessary to access
|
||||
// a different resource in the set.
|
||||
func (m *RequestValidator) pruneResourceRequestRoles(
|
||||
ctx context.Context,
|
||||
resourceIDs []types.ResourceID,
|
||||
|
||||
@@ -202,11 +202,11 @@ func matchResourceByFilters(resource types.ResourceWithLabels, filter MatchResou
|
||||
}
|
||||
|
||||
// matchAndFilterKubeClusters is similar to MatchResourceByFilters, but does two things in addition:
|
||||
// 1) handles kube service having a 1-N relationship (service-clusters)
|
||||
// 1. handles kube service having a 1-N relationship (service-clusters)
|
||||
// so each kube cluster goes through the filters
|
||||
// 2) filters out the non-matched clusters on the kube service and the kube service is
|
||||
// 2. filters out the non-matched clusters on the kube service and the kube service is
|
||||
// modified in place with only the matched clusters
|
||||
// 3) only returns true if the service contained any matched cluster
|
||||
// 3. only returns true if the service contained any matched cluster
|
||||
func matchAndFilterKubeClusters(resource types.ResourceWithLabels, filter MatchResourceFilter) (bool, error) {
|
||||
if len(filter.Labels) == 0 && len(filter.SearchKeywords) == 0 && filter.PredicateExpression == "" {
|
||||
return true, nil
|
||||
|
||||
@@ -653,9 +653,10 @@ func newParserForIdentifierSubcondition(ctx RuleContext, identifier string) (pre
|
||||
// NewResourceParser returns a parser made for boolean expressions based on a
|
||||
// json-serialiable resource. Customized to allow short identifiers common in all
|
||||
// resources:
|
||||
// - `metadata.name` can be referenced with `name` ie: `name == "jenkins"``
|
||||
// - `metadata.labels + spec.dynamic_labels` can be referenced with `labels`
|
||||
// - `metadata.name` can be referenced with `name` ie: `name == "jenkins"“
|
||||
// - `metadata.labels + spec.dynamic_labels` can be referenced with `labels`
|
||||
// ie: `labels.env == "prod"`
|
||||
//
|
||||
// All other fields can be referenced by starting expression with identifier `resource`
|
||||
// followed by the names of the json fields ie: `resource.spec.public_addr`.
|
||||
func NewResourceParser(resource types.ResourceWithLabels) (BoolPredicateParser, error) {
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
)
|
||||
|
||||
//MarshalPluginData marshals the PluginData resource to JSON.
|
||||
// MarshalPluginData marshals the PluginData resource to JSON.
|
||||
func MarshalPluginData(pluginData types.PluginData, opts ...MarshalOption) ([]byte, error) {
|
||||
if err := pluginData.CheckAndSetDefaults(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
||||
@@ -416,6 +416,7 @@ func applyValueTraitsSlice(inputs []string, traits map[string][]string, fieldNam
|
||||
// and traits from identity provider. For example:
|
||||
//
|
||||
// cluster_labels:
|
||||
//
|
||||
// env: ['{{external.groups}}']
|
||||
//
|
||||
// and groups: ['admins', 'devs']
|
||||
@@ -423,6 +424,7 @@ func applyValueTraitsSlice(inputs []string, traits map[string][]string, fieldNam
|
||||
// will be interpolated to:
|
||||
//
|
||||
// cluster_labels:
|
||||
//
|
||||
// env: ['admins', 'devs']
|
||||
func applyLabelsTraits(inLabels types.Labels, traits map[string][]string) types.Labels {
|
||||
outLabels := make(types.Labels, len(inLabels))
|
||||
|
||||
+10
-11
@@ -3964,22 +3964,21 @@ func TestCheckAccessToWindowsDesktop(t *testing.T) {
|
||||
//
|
||||
// To run benchmark:
|
||||
//
|
||||
// go test -bench=.
|
||||
// go test -bench=.
|
||||
//
|
||||
// To run benchmark and obtain CPU and memory profiling:
|
||||
//
|
||||
// go test -bench=. -cpuprofile=cpu.prof -memprofile=mem.prof
|
||||
// go test -bench=. -cpuprofile=cpu.prof -memprofile=mem.prof
|
||||
//
|
||||
// To use the command line tool to read the profile:
|
||||
//
|
||||
// go tool pprof cpu.prof
|
||||
// go tool pprof cpu.prof
|
||||
// go tool pprof cpu.prof
|
||||
// go tool pprof cpu.prof
|
||||
//
|
||||
// To generate a graph:
|
||||
//
|
||||
// go tool pprof --pdf cpu.prof > cpu.pdf
|
||||
// go tool pprof --pdf mem.prof > mem.pdf
|
||||
//
|
||||
// go tool pprof --pdf cpu.prof > cpu.pdf
|
||||
// go tool pprof --pdf mem.prof > mem.pdf
|
||||
func BenchmarkCheckAccessToServer(b *testing.B) {
|
||||
servers := make([]*types.ServerV2, 0, 4000)
|
||||
|
||||
@@ -4717,7 +4716,7 @@ func TestHostUsers_HostSudoers(t *testing.T) {
|
||||
server types.Server
|
||||
}{
|
||||
{
|
||||
test: "test exact match, one sudoer entry, one role",
|
||||
test: "test exact match, one sudoer entry, one role",
|
||||
sudoers: []string{"%sudo ALL=(ALL) ALL"},
|
||||
roles: NewRoleSet(&types.RoleV5{
|
||||
|
||||
@@ -4726,7 +4725,7 @@ func TestHostUsers_HostSudoers(t *testing.T) {
|
||||
CreateHostUser: types.NewBoolOption(true),
|
||||
},
|
||||
Allow: types.RoleConditions{
|
||||
NodeLabels: types.Labels{"success": []string{"abc"}},
|
||||
NodeLabels: types.Labels{"success": []string{"abc"}},
|
||||
HostSudoers: []string{"%sudo ALL=(ALL) ALL"},
|
||||
},
|
||||
},
|
||||
@@ -4790,7 +4789,7 @@ func TestHostUsers_HostSudoers(t *testing.T) {
|
||||
CreateHostUser: types.NewBoolOption(true),
|
||||
},
|
||||
Allow: types.RoleConditions{
|
||||
NodeLabels: types.Labels{"success": []string{"abc"}},
|
||||
NodeLabels: types.Labels{"success": []string{"abc"}},
|
||||
HostSudoers: []string{"%sudo ALL=(ALL) ALL"},
|
||||
},
|
||||
},
|
||||
@@ -4814,7 +4813,7 @@ func TestHostUsers_HostSudoers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "line deny",
|
||||
test: "line deny",
|
||||
sudoers: []string{"%sudo ALL=(ALL) ALL"},
|
||||
roles: NewRoleSet(&types.RoleV5{
|
||||
Spec: types.RoleSpecV5{
|
||||
|
||||
+21
-16
@@ -42,36 +42,41 @@ func newBufferedConn(conn net.Conn, header io.Reader) *bufferedConn {
|
||||
//
|
||||
// Example: Prepend Read buff to the connection.
|
||||
// conn, err := conn.Read(buff)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// Now the client can peek at buff read by conn.Read call.
|
||||
//
|
||||
// But to not alter the connection the buff can be prepended to the connection and
|
||||
// the buffered connection should be sued for further operations.
|
||||
// conn = newBufferedConn(conn, bytes.NewReader(buff))
|
||||
// if err := handleConnection(conn); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// if err := handleConnection(conn); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// The bufferedConn is useful in more complex cases when connection Read call is done in an external library
|
||||
// Example: Reading the client TLS Hello message TLS termination.
|
||||
// var hello *tls.ClientHelloInfo
|
||||
// buff := new(bytes.Buffer)
|
||||
// tlsConn := tls.Server(readOnlyConn{reader: io.TeeReader(conn, buff)}, &tls.Config{
|
||||
// GetConfigForClient: func(info *tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
// hello = info
|
||||
// return nil, nil
|
||||
// },
|
||||
// })
|
||||
//
|
||||
// tlsConn := tls.Server(readOnlyConn{reader: io.TeeReader(conn, buff)}, &tls.Config{
|
||||
// GetConfigForClient: func(info *tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
// hello = info
|
||||
// return nil, nil
|
||||
// },
|
||||
// })
|
||||
//
|
||||
// err := tlsConn.Handshake()
|
||||
// if hello == nil {
|
||||
// return trace.Wrap(err)
|
||||
// }
|
||||
//
|
||||
// if hello == nil {
|
||||
// return trace.Wrap(err)
|
||||
// }
|
||||
//
|
||||
// Create the bufferedConn with prepended buff obtained from TLS Handshake.
|
||||
// conn := newBufferedConn(conn, buff)
|
||||
//
|
||||
type bufferedConn struct {
|
||||
net.Conn
|
||||
r io.Reader
|
||||
|
||||
@@ -353,14 +353,14 @@ type ConnectionInfo struct {
|
||||
type HandlerFuncWithInfo func(ctx context.Context, conn net.Conn, info ConnectionInfo) error
|
||||
|
||||
// handleConn routes incoming connection based on SNI TLS information to the proper Handler by following steps:
|
||||
// 1) Read TLS hello message without TLS termination and returns conn that will be used for further operations.
|
||||
// 2) Get routing rules for p.Router.Router based on SNI and ALPN fields read in step 1.
|
||||
// 3) If the selected handler was configured with the ForwardTLS
|
||||
// forwards the connection to the handler without TLS termination.
|
||||
// 4) Trigger TLS handshake and terminates the TLS connection.
|
||||
// 5) For backward compatibility check RouteToDatabase identity field
|
||||
// was set if yes forward to the generic TLS DB handler.
|
||||
// 6) Forward connection to the handler obtained in step 2.
|
||||
// 1. Read TLS hello message without TLS termination and returns conn that will be used for further operations.
|
||||
// 2. Get routing rules for p.Router.Router based on SNI and ALPN fields read in step 1.
|
||||
// 3. If the selected handler was configured with the ForwardTLS
|
||||
// forwards the connection to the handler without TLS termination.
|
||||
// 4. Trigger TLS handshake and terminates the TLS connection.
|
||||
// 5. For backward compatibility check RouteToDatabase identity field
|
||||
// was set if yes forward to the generic TLS DB handler.
|
||||
// 6. Forward connection to the handler obtained in step 2.
|
||||
func (p *Proxy) handleConn(ctx context.Context, clientConn net.Conn, defaultOverride *tls.Config) error {
|
||||
hello, conn, err := p.readHelloMessageWithoutTLSTermination(clientConn)
|
||||
if err != nil {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
@@ -398,9 +399,14 @@ func TestProxyMakeConnectionHandler(t *testing.T) {
|
||||
require.Equal(t, string(common.ProtocolHTTP), clientTLSConn.ConnectionState().NegotiatedProtocol)
|
||||
require.NoError(t, req.Write(clientTLSConn))
|
||||
|
||||
response, err := http.ReadResponse(bufio.NewReader(clientTLSConn), req)
|
||||
resp, err := http.ReadResponse(bufio.NewReader(clientTLSConn), req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, response.StatusCode)
|
||||
|
||||
// Always drain/close the body.
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Wait until handler is done. And verify context is canceled, NOT deadline exceeded.
|
||||
<-handlerCtx.Done()
|
||||
|
||||
+11
-11
@@ -124,18 +124,18 @@ func (s *SigningServiceConfig) CheckAndSetDefaults() error {
|
||||
// Handling steps:
|
||||
// 1) Decoded Authorization Header. Authorization Header example:
|
||||
//
|
||||
// Authorization: AWS4-HMAC-SHA256
|
||||
// Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,
|
||||
// SignedHeaders=host;range;x-amz-date,
|
||||
// Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
|
||||
// Authorization: AWS4-HMAC-SHA256
|
||||
// Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,
|
||||
// SignedHeaders=host;range;x-amz-date,
|
||||
// Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
|
||||
//
|
||||
// 2) Extract credential section from credential Authorization Header.
|
||||
// 3) Extract aws-region and aws-service from the credential section.
|
||||
// 4) Build AWS API endpoint based on extracted aws-region and aws-service fields.
|
||||
// Not that for endpoint resolving the https://github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
|
||||
// package is used and when Amazon releases a new API the dependency update is needed.
|
||||
// 5) Sign HTTP request.
|
||||
// 6) Forward the signed HTTP request to the AWS API.
|
||||
// 2. Extract credential section from credential Authorization Header.
|
||||
// 3. Extract aws-region and aws-service from the credential section.
|
||||
// 4. Build AWS API endpoint based on extracted aws-region and aws-service fields.
|
||||
// Not that for endpoint resolving the https://github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
|
||||
// package is used and when Amazon releases a new API the dependency update is needed.
|
||||
// 5. Sign HTTP request.
|
||||
// 6. Forward the signed HTTP request to the AWS API.
|
||||
func (s *SigningService) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
sessionCtx, err := common.GetSessionContext(req)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
|
||||
@@ -30,9 +30,9 @@ limitations under the License.
|
||||
//
|
||||
// For example, this configuration will make Teleport to connect to a secondary:
|
||||
//
|
||||
// - name: "mongo-rs"
|
||||
// protocol: "mongodb"
|
||||
// uri: "mongodb://mongo1:27017,mongo2:27017/?replicaSet=rs0&readPreference=secondary"
|
||||
// - name: "mongo-rs"
|
||||
// protocol: "mongodb"
|
||||
// uri: "mongodb://mongo1:27017,mongo2:27017/?replicaSet=rs0&readPreference=secondary"
|
||||
//
|
||||
// Command authorization
|
||||
// =====================
|
||||
|
||||
@@ -102,14 +102,14 @@ func (e *Engine) HandleConnection(ctx context.Context, sessionCtx *common.Sessio
|
||||
|
||||
// handleClientMessage implements the client message's roundtrip which can go
|
||||
// down a few different ways:
|
||||
// 1. If the client's command is not allowed by user's role, we do not pass it
|
||||
// to the server and return an error to the client.
|
||||
// 2. In the most common case, we send client message to the server, read its
|
||||
// reply and send it back to the client.
|
||||
// 3. Some client commands do not receive a reply in which case we just return
|
||||
// after sending message to the server and wait for next client message.
|
||||
// 4. Server can also send multiple messages in a row in which case we exhaust
|
||||
// them before returning to listen for next client message.
|
||||
// 1. If the client's command is not allowed by user's role, we do not pass it
|
||||
// to the server and return an error to the client.
|
||||
// 2. In the most common case, we send client message to the server, read its
|
||||
// reply and send it back to the client.
|
||||
// 3. Some client commands do not receive a reply in which case we just return
|
||||
// after sending message to the server and wait for next client message.
|
||||
// 4. Server can also send multiple messages in a row in which case we exhaust
|
||||
// them before returning to listen for next client message.
|
||||
func (e *Engine) handleClientMessage(ctx context.Context, sessionCtx *common.Session, clientMessage protocol.Message, clientConn net.Conn, serverConn driver.Connection) error {
|
||||
e.Log.Debugf("===> %v", clientMessage)
|
||||
// First check the client command against user's role and log in the audit.
|
||||
|
||||
@@ -30,18 +30,18 @@ limitations under the License.
|
||||
//
|
||||
// Package layout:
|
||||
//
|
||||
// * message.go: Defines wire message common interface and provides methods for
|
||||
// reading wire messages from client/server connections.
|
||||
// - message.go: Defines wire message common interface and provides methods for
|
||||
// reading wire messages from client/server connections.
|
||||
//
|
||||
// * opmsg.go: Contains marshal/unmarshal for OP_MSG - extensible message that
|
||||
// MongoDB 3.6 and higher use for all commands.
|
||||
// - opmsg.go: Contains marshal/unmarshal for OP_MSG - extensible message that
|
||||
// MongoDB 3.6 and higher use for all commands.
|
||||
//
|
||||
// * opquery.go: Contains marshal/unmarshal for OP_QUERY - a legacy command,
|
||||
// still used for some operations (e.g. first "isMaster" handshake message).
|
||||
// - opquery.go: Contains marshal/unmarshal for OP_QUERY - a legacy command,
|
||||
// still used for some operations (e.g. first "isMaster" handshake message).
|
||||
//
|
||||
// * opreply.go: Contains marshal/unmarshal for OP_REPLY - a reply message sent
|
||||
// by a database to an OP_QUERY command.
|
||||
// - opreply.go: Contains marshal/unmarshal for OP_REPLY - a reply message sent
|
||||
// by a database to an OP_QUERY command.
|
||||
//
|
||||
// * errors.go: Provides methods for sending errors in wire message to client
|
||||
// connections.
|
||||
// - errors.go: Provides methods for sending errors in wire message to client
|
||||
// connections.
|
||||
package protocol
|
||||
|
||||
@@ -30,13 +30,13 @@ import (
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_compressed
|
||||
//
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 originalOpcode; // value of wrapped opcode
|
||||
// int32 uncompressedSize; // size of deflated compressedMessage, excluding MsgHeader
|
||||
// uint8 compressorId; // ID of compressor that compressed message
|
||||
// char *compressedMessage; // opcode itself, excluding MsgHeader
|
||||
// }
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 originalOpcode; // value of wrapped opcode
|
||||
// int32 uncompressedSize; // size of deflated compressedMessage, excluding MsgHeader
|
||||
// uint8 compressorId; // ID of compressor that compressed message
|
||||
// char *compressedMessage; // opcode itself, excluding MsgHeader
|
||||
// }
|
||||
type MessageOpCompressed struct {
|
||||
Header MessageHeader
|
||||
OriginalOpcode wiremessage.OpCode
|
||||
|
||||
@@ -30,13 +30,13 @@ import (
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_delete
|
||||
//
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 ZERO; // 0 - reserved for future use
|
||||
// cstring fullCollectionName; // "dbname.collectionname"
|
||||
// int32 flags; // bit vector - see below for details.
|
||||
// document selector; // query object. See below for details.
|
||||
// }
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 ZERO; // 0 - reserved for future use
|
||||
// cstring fullCollectionName; // "dbname.collectionname"
|
||||
// int32 flags; // bit vector - see below for details.
|
||||
// document selector; // query object. See below for details.
|
||||
// }
|
||||
//
|
||||
// OP_DELETE is deprecated starting MongoDB 5.0 in favor of OP_MSG.
|
||||
type MessageOpDelete struct {
|
||||
|
||||
@@ -30,13 +30,13 @@ import (
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_get_more
|
||||
//
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 ZERO; // 0 - reserved for future use
|
||||
// cstring fullCollectionName; // "dbname.collectionname"
|
||||
// int32 numberToReturn; // number of documents to return
|
||||
// int64 cursorID; // cursorID from the OP_REPLY
|
||||
// }
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 ZERO; // 0 - reserved for future use
|
||||
// cstring fullCollectionName; // "dbname.collectionname"
|
||||
// int32 numberToReturn; // number of documents to return
|
||||
// int64 cursorID; // cursorID from the OP_REPLY
|
||||
// }
|
||||
//
|
||||
// OP_GET_MORE is deprecated starting MongoDB 5.0 in favor of OP_MSG.
|
||||
type MessageOpGetMore struct {
|
||||
|
||||
@@ -30,12 +30,12 @@ import (
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_insert
|
||||
//
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 flags; // bit vector - see below
|
||||
// cstring fullCollectionName; // "dbname.collectionname"
|
||||
// document* documents; // one or more documents to insert into the collection
|
||||
// }
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 flags; // bit vector - see below
|
||||
// cstring fullCollectionName; // "dbname.collectionname"
|
||||
// document* documents; // one or more documents to insert into the collection
|
||||
// }
|
||||
//
|
||||
// OP_INSERT is deprecated starting MongoDB 5.0 in favor of OP_MSG.
|
||||
type MessageOpInsert struct {
|
||||
|
||||
@@ -29,12 +29,12 @@ import (
|
||||
//
|
||||
// https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#op_kill_cursors
|
||||
//
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 ZERO; // 0 - reserved for future use
|
||||
// int32 numberOfCursorIDs; // number of cursorIDs in message
|
||||
// int64* cursorIDs; // sequence of cursorIDs to close
|
||||
// }
|
||||
// struct {
|
||||
// MsgHeader header; // standard message header
|
||||
// int32 ZERO; // 0 - reserved for future use
|
||||
// int32 numberOfCursorIDs; // number of cursorIDs in message
|
||||
// int64* cursorIDs; // sequence of cursorIDs to close
|
||||
// }
|
||||
//
|
||||
// OP_KILL_CURSORS is deprecated starting MongoDB 5.0 in favor of OP_MSG.
|
||||
type MessageOpKillCursors struct {
|
||||
|
||||
@@ -30,12 +30,12 @@ import (
|
||||
//
|
||||
// https://docs.mongodb.com/master/reference/mongodb-wire-protocol/#op-msg
|
||||
//
|
||||
// OP_MSG {
|
||||
// MsgHeader header; // standard message header
|
||||
// uint32 flagBits; // message flags
|
||||
// Sections[] sections; // data sections
|
||||
// optional<uint32> checksum; // optional CRC-32C checksum
|
||||
// }
|
||||
// OP_MSG {
|
||||
// MsgHeader header; // standard message header
|
||||
// uint32 flagBits; // message flags
|
||||
// Sections[] sections; // data sections
|
||||
// optional<uint32> checksum; // optional CRC-32C checksum
|
||||
// }
|
||||
type MessageOpMsg struct {
|
||||
Header MessageHeader
|
||||
Flags wiremessage.MsgFlag
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user