mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-02 14:59:53 +08:00
This PR includes a new Role resource version that is compatible with V5 spec.
The new resource introduces the `kubernetes_resources` definition that allows operators to limit the Kubernetes resources that each member can access. The `kubernetes_resources` entries must follow the following format: `{"kind":"<kind>", "namespace":"<namespace>","name":"<pod>"}`. Currently, it only supports objects of `kind` `pod`. Valid examples `<namespace>/<name>:
- `*/*`: matches all pods in all namespaces.
- `default/*`: matches all pods in the `default` namespace.
- `*/nginx-*`: matches every pod prefixed with `nginx-` in every namespace.
For older resource versions - V5, V4, V3 - `kubernetes_resources` is automatically populated with `{"kind":"pod","namespace":"*","name":"*"}` to keep compatibility. For the newest version, it's mandatory to define its value otherwise access to pods will be denied.
Part of #18434
126 lines
3.9 KiB
Go
126 lines
3.9 KiB
Go
/*
|
|
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 tbot
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/gravitational/teleport/api/identityfile"
|
|
"github.com/gravitational/teleport/api/types"
|
|
"github.com/gravitational/teleport/lib/tbot/bot"
|
|
"github.com/gravitational/teleport/lib/tbot/config"
|
|
"github.com/gravitational/teleport/lib/tbot/testhelpers"
|
|
"github.com/gravitational/teleport/lib/tlsca"
|
|
"github.com/gravitational/teleport/lib/utils"
|
|
)
|
|
|
|
// Note: This test lives in main to avoid otherwise inevitable import cycles
|
|
// if we tried importing renewal code from the config package.
|
|
|
|
// validateTemplate loads and validates a config template from the destination
|
|
func validateTemplate(t *testing.T, tplI config.Template, dest bot.Destination) {
|
|
t.Helper()
|
|
|
|
// First, make sure all advertised files exist.
|
|
for _, file := range tplI.Describe(dest) {
|
|
// Don't bother checking directories, they're meant to be black
|
|
// boxes. We could implement type-specific checks if we really
|
|
// wanted.
|
|
if file.IsDir {
|
|
continue
|
|
}
|
|
|
|
bytes, err := dest.Read(file.Name)
|
|
require.NoError(t, err)
|
|
|
|
// Should at least be non-empty.
|
|
t.Logf("Expected file %q for template %q has length: %d", file.Name, tplI.Name(), len(bytes))
|
|
require.Truef(t, len(bytes) > 0, "file %q in template %q must be non-empty", file.Name, tplI.Name())
|
|
}
|
|
|
|
// Next, for supported template types, make sure they're valid.
|
|
// TODO: consider adding further type-specific tests.
|
|
switch tpl := tplI.(type) {
|
|
case *config.TemplateIdentity:
|
|
// Make sure the identityfile package can read this identity file.
|
|
b, err := dest.Read(tpl.FileName)
|
|
require.NoError(t, err)
|
|
|
|
buf := bytes.NewBuffer(b)
|
|
_, err = identityfile.Read(buf)
|
|
require.NoError(t, err)
|
|
case *config.TemplateTLSCAs:
|
|
b, err := dest.Read(tpl.HostCAPath)
|
|
require.NoError(t, err)
|
|
_, err = tlsca.ParseCertificatePEM(b)
|
|
require.NoError(t, err)
|
|
|
|
b, err = dest.Read(tpl.UserCAPath)
|
|
require.NoError(t, err)
|
|
_, err = tlsca.ParseCertificatePEM(b)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
// TestTemplateRendering performs a full renewal and ensures all expected
|
|
// default config templates are present.
|
|
func TestDefaultTemplateRendering(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Make a new auth server.
|
|
log := utils.NewLoggerForTests()
|
|
fc, fds := testhelpers.DefaultConfig(t)
|
|
_ = testhelpers.MakeAndRunTestAuthServer(t, log, fc, fds)
|
|
rootClient := testhelpers.MakeDefaultAuthClient(t, log, fc)
|
|
|
|
// Make and join a new bot instance.
|
|
const roleName = "dummy-role"
|
|
role, err := types.NewRole(roleName, types.RoleSpecV6{})
|
|
require.NoError(t, err)
|
|
require.NoError(t, rootClient.UpsertRole(context.Background(), role))
|
|
|
|
botParams := testhelpers.MakeBot(t, rootClient, "test", roleName)
|
|
botConfig := testhelpers.MakeMemoryBotConfig(t, fc, botParams)
|
|
storage, err := botConfig.Storage.GetDestination()
|
|
require.NoError(t, err)
|
|
b := New(botConfig, log, nil)
|
|
|
|
ident, err := b.getIdentityFromToken()
|
|
require.NoError(t, err)
|
|
botClient := testhelpers.MakeBotAuthClient(t, fc, ident)
|
|
b._ident = ident
|
|
b._client = botClient
|
|
|
|
err = b.renew(context.Background(), storage)
|
|
require.NoError(t, err)
|
|
|
|
dest := botConfig.Destinations[0]
|
|
destImpl, err := dest.GetDestination()
|
|
require.NoError(t, err)
|
|
|
|
for _, templateName := range config.GetRequiredConfigs() {
|
|
cfg := dest.GetConfigByName(templateName)
|
|
require.NotNilf(t, cfg, "template %q must exist", templateName)
|
|
|
|
validateTemplate(t, cfg, destImpl)
|
|
}
|
|
}
|