Skip to content

Commit

Permalink
Merge branch 'branch/v9' into bot/backport-13205-branch/v9
Browse files Browse the repository at this point in the history
  • Loading branch information
xacrimon authored Jun 15, 2022
2 parents 0aa21d7 + a8e8b91 commit 005712b
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 23 deletions.
12 changes: 6 additions & 6 deletions api/types/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,24 +279,24 @@ func (c *LicenseV3) SetSupportsDatabaseAccess(value Bool) {
c.Spec.SupportsDatabaseAccess = value
}

// GetSupportsDesktopAccess returns database access support flag
// GetSupportsDesktopAccess returns desktop access support flag
func (c *LicenseV3) GetSupportsDesktopAccess() Bool {
return c.Spec.SupportsDesktopAccess
}

// SetSupportsDesktopAccess sets database access support flag
// SetSupportsDesktopAccess sets desktop access support flag
func (c *LicenseV3) SetSupportsDesktopAccess(value Bool) {
c.Spec.SupportsDesktopAccess = value
}

// GetSupportsModeratedSessions returns database access support flag
// GetSupportsModeratedSessions returns moderated sessions support flag
func (c *LicenseV3) GetSupportsModeratedSessions() Bool {
return c.Spec.SupportsDesktopAccess
return c.Spec.SupportsModeratedSessions
}

// SetSupportsModeratedSessions sets database access support flag
// SetSupportsModeratedSessions sets moderated sessions support flag
func (c *LicenseV3) SetSupportsModeratedSessions(value Bool) {
c.Spec.SupportsDesktopAccess = value
c.Spec.SupportsModeratedSessions = value
}

// String represents a human readable version of license enabled features
Expand Down
130 changes: 130 additions & 0 deletions api/types/license_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
Copyright 2022 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package types

import (
"reflect"
"runtime"
"testing"

"github.com/stretchr/testify/require"
)

func TestLicenseSettersAndGetters(t *testing.T) {
// All getters inspected in this test.
allFields := []func(License) Bool{
License.GetReportsUsage,
License.GetCloud,
License.GetSupportsKubernetes,
License.GetSupportsApplicationAccess,
License.GetSupportsDatabaseAccess,
License.GetSupportsDesktopAccess,
License.GetSupportsModeratedSessions,
}

// unsetFields returns a list of license fields getters minus
// the one passed as an argument.
unsetFields := func(getter func(License) Bool) []func(License) Bool {
var unsetFields []func(License) Bool
for _, fieldGetter := range allFields {
if fnName(fieldGetter) != fnName(getter) {
unsetFields = append(unsetFields, fieldGetter)
}
}
return unsetFields
}

tt := []struct {
name string
setter func(License, Bool)
getter func(License) Bool
unsetFields [](func(License) Bool)
}{
{
name: "Set ReportsUsage",
setter: License.SetReportsUsage,
getter: License.GetReportsUsage,
unsetFields: unsetFields(License.GetReportsUsage),
},
{
name: "Set Cloud",
setter: License.SetCloud,
getter: License.GetCloud,
unsetFields: unsetFields(License.GetCloud),
},
{
name: "Set Kubernetes Support",
setter: License.SetSupportsKubernetes,
getter: License.GetSupportsKubernetes,
unsetFields: unsetFields(License.GetSupportsKubernetes),
},
{
name: "Set Application Access Support",
setter: License.SetSupportsApplicationAccess,
getter: License.GetSupportsApplicationAccess,
unsetFields: unsetFields(License.GetSupportsApplicationAccess),
},
{
name: "Set Database Access Support",
setter: License.SetSupportsDatabaseAccess,
getter: License.GetSupportsDatabaseAccess,
unsetFields: unsetFields(License.GetSupportsDatabaseAccess),
},
{
name: "Set Desktop Access Support",
setter: License.SetSupportsDesktopAccess,
getter: License.GetSupportsDesktopAccess,
unsetFields: unsetFields(License.GetSupportsDesktopAccess),
},
{
name: "Set Moderated Sessions Support",
setter: License.SetSupportsModeratedSessions,
getter: License.GetSupportsModeratedSessions,
unsetFields: unsetFields(License.GetSupportsModeratedSessions),
},
}

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
license := &LicenseV3{
Spec: LicenseSpecV3{
SupportsApplicationAccess: NewBoolP(false),
},
}
tc.setter(license, true)
require.True(t, bool(tc.getter(license)))
for _, unset := range tc.unsetFields {
require.False(t, bool(unset(license)))
}
})
}

// Manually test Application Access.
// If unset application access is set to true by default.
license := &LicenseV3{}
require.True(t, bool(license.GetSupportsApplicationAccess()))
require.False(t, bool(license.GetReportsUsage()))
require.False(t, bool(license.GetCloud()))
require.False(t, bool(license.GetSupportsKubernetes()))
require.False(t, bool(license.GetSupportsDatabaseAccess()))
require.False(t, bool(license.GetSupportsDesktopAccess()))
require.False(t, bool(license.GetSupportsModeratedSessions()))
}

func fnName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
2 changes: 1 addition & 1 deletion docs/pages/cloud/downloads.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Description | | | | |
-----------------------------------|-|-|-|-|
Linux Debian Packages | [amd64](https://get.gravitational.com/teleport-ent_(=cloud.version=)_amd64.deb) | [arm64](https://get.gravitational.com/teleport-ent_(=cloud.version=)_arm64.deb) | [armv7](https://get.gravitational.com/teleport-ent_(=cloud.version=)_arm.deb) | [i386](https://get.gravitational.com/teleport-ent_(=cloud.version=)_i386.deb) |
Linux RPM Packages | [amd64](https://get.gravitational.com/teleport-ent-(=cloud.version=)-1.x86_64.rpm) | [arm64](https://get.gravitational.com/teleport-ent-(=cloud.version=)-1.arm64.rpm) | [armv7](https://get.gravitational.com/teleport-ent-(=cloud.version=)-1.arm.rpm) | [i386](https://get.gravitational.com/teleport-ent-(=cloud.version=)-1.i386.rpm) |
macOS Packages | [amd64](https://get.gravitational.com/teleport-(=cloud.version=).pkg) |
macOS Packages | [amd64](https://get.gravitational.com/teleport-ent-(=cloud.version=).pkg) |

## Teleport client-only packages

Expand Down
14 changes: 9 additions & 5 deletions lib/service/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ import (
"github.com/gravitational/trace"
)

func (process *TeleportProcess) shouldInitDatabases() bool {
databasesCfg := len(process.Config.Databases.Databases) > 0
resourceMatchersCfg := len(process.Config.Databases.ResourceMatchers) > 0
awsMatchersCfg := len(process.Config.Databases.AWSMatchers) > 0
anyCfg := databasesCfg || resourceMatchersCfg || awsMatchersCfg

return process.Config.Databases.Enabled && anyCfg
}

func (process *TeleportProcess) initDatabases() {
if len(process.Config.Databases.Databases) == 0 &&
len(process.Config.Databases.ResourceMatchers) == 0 &&
len(process.Config.Databases.AWSMatchers) == 0 {
return
}
process.registerWithAuthServer(types.RoleDatabase, DatabasesIdentityEvent)
process.RegisterCriticalFunc("db.init", process.initDatabaseService)
}
Expand Down
69 changes: 69 additions & 0 deletions lib/service/db_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2022 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package service

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestTeleportProcess_shouldInitDatabases(t *testing.T) {
t.Parallel()
tests := []struct {
name string
config DatabasesConfig
want bool
}{
{
name: "disabled",
config: DatabasesConfig{
Enabled: false,
},
want: false,
},
{
name: "enabled but no config",
config: DatabasesConfig{
Enabled: true,
},
want: false,
},
{
name: "enabled with config",
config: DatabasesConfig{
Enabled: true,
Databases: []Database{
{
Name: "foo",
},
},
},
want: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &TeleportProcess{
Config: &Config{
Databases: tt.config,
},
}
require.Equal(t, tt.want, p.shouldInitDatabases())
})
}
}
16 changes: 8 additions & 8 deletions lib/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ func NewTeleport(cfg *Config, opts ...NewTeleportOption) (*TeleportProcess, erro
// create the data directory if it's missing
_, err = os.Stat(cfg.DataDir)
if os.IsNotExist(err) {
err := os.MkdirAll(cfg.DataDir, os.ModeDir|0700)
err := os.MkdirAll(cfg.DataDir, os.ModeDir|0o700)
if err != nil {
if errors.Is(err, fs.ErrPermission) {
cfg.Log.Errorf("Teleport does not have permission to write to: %v. Ensure that you are running as a user with appropriate permissions.", cfg.DataDir)
Expand Down Expand Up @@ -764,7 +764,7 @@ func NewTeleport(cfg *Config, opts ...NewTeleportOption) (*TeleportProcess, erro
ec2Hostname, err := imClient.GetTagValue(supervisor.ExitContext(), types.EC2HostnameTag)
if err == nil {
if ec2Hostname != "" {
cfg.Log.Info("Found %q tag in EC2 instance. Using %q as hostname.", types.EC2HostnameTag, ec2Hostname)
cfg.Log.Infof("Found %q tag in EC2 instance. Using %q as hostname.", types.EC2HostnameTag, ec2Hostname)
cfg.Hostname = ec2Hostname
}
} else if !trace.IsNotFound(err) {
Expand Down Expand Up @@ -858,7 +858,7 @@ func NewTeleport(cfg *Config, opts ...NewTeleportOption) (*TeleportProcess, erro
if cfg.Apps.Enabled {
eventMapping.In = append(eventMapping.In, AppsReady)
}
if cfg.Databases.Enabled {
if process.shouldInitDatabases() {
eventMapping.In = append(eventMapping.In, DatabasesReady)
}
if cfg.Metrics.Enabled {
Expand Down Expand Up @@ -911,7 +911,7 @@ func NewTeleport(cfg *Config, opts ...NewTeleportOption) (*TeleportProcess, erro
warnOnErr(process.closeImportedDescriptors(teleport.ComponentApp), process.log)
}

if cfg.Databases.Enabled {
if process.shouldInitDatabases() {
process.initDatabases()
serviceStarted = true
} else {
Expand Down Expand Up @@ -949,7 +949,7 @@ func NewTeleport(cfg *Config, opts ...NewTeleportOption) (*TeleportProcess, erro

// create the new pid file only after started successfully
if cfg.PIDFile != "" {
f, err := os.OpenFile(cfg.PIDFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
f, err := os.OpenFile(cfg.PIDFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o666)
if err != nil {
return nil, trace.ConvertSystemError(err)
}
Expand Down Expand Up @@ -2186,7 +2186,7 @@ func (process *TeleportProcess) initUploaderService(uploaderCfg filesessions.Upl
for i := 1; i < len(path); i++ {
dir := filepath.Join(path[:i+1]...)
log.Infof("Creating directory %v.", dir)
err := os.Mkdir(dir, 0755)
err := os.Mkdir(dir, 0o755)
err = trace.ConvertSystemError(err)
if err != nil {
if !trace.IsAlreadyExists(err) {
Expand Down Expand Up @@ -4061,10 +4061,10 @@ func initSelfSignedHTTPSCert(cfg *Config) (err error) {
return trace.Wrap(err)
}

if err := ioutil.WriteFile(keyPath, creds.PrivateKey, 0600); err != nil {
if err := ioutil.WriteFile(keyPath, creds.PrivateKey, 0o600); err != nil {
return trace.Wrap(err, "error writing key PEM")
}
if err := ioutil.WriteFile(certPath, creds.Cert, 0600); err != nil {
if err := ioutil.WriteFile(certPath, creds.Cert, 0o600); err != nil {
return trace.Wrap(err, "error writing key PEM")
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion lib/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func TestServiceCheckPrincipals(t *testing.T) {
ServerIdentity: tlsServer.Identity,
}

var tests = []struct {
tests := []struct {
inPrincipals []string
inDNS []string
outRegenerate bool
Expand Down
23 changes: 21 additions & 2 deletions lib/utils/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import (
"context"
"fmt"
"io"
"net/http"
"regexp"
"strings"
"time"

"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
Expand All @@ -32,6 +34,10 @@ import (
// metadataReadLimit is the largest number of bytes that will be read from imds responses.
const metadataReadLimit = 1_000_000

// instanceMetadataURL is the URL for EC2 instance metadata.
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
const instanceMetadataURL = "http://169.254.169.254/latest/meta-data"

// GetEC2IdentityDocument fetches the PKCS7 RSA2048 InstanceIdentityDocument
// from the IMDS for this EC2 instance.
func GetEC2IdentityDocument() ([]byte, error) {
Expand Down Expand Up @@ -109,8 +115,21 @@ func NewInstanceMetadataClient(ctx context.Context) (*InstanceMetadataClient, er

// IsAvailable checks if instance metadata is available.
func (client *InstanceMetadataClient) IsAvailable(ctx context.Context) bool {
_, err := client.getMetadata(ctx, "")
return err == nil
// Doing this check via imds.Client.GetMetadata() involves several unrelated requests and takes a few seconds
// to complete when not on EC2. This approach is faster.
httpClient := http.Client{
Timeout: 250 * time.Millisecond,
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, instanceMetadataURL, nil)
if err != nil {
return false
}
resp, err := httpClient.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}

// getMetadata gets the raw metadata from a specified path.
Expand Down

0 comments on commit 005712b

Please sign in to comment.