Files
teleport/lib/autoupdate/agent/config_test.go
T
Angel Dionisio 15136eb0d8 Sign managed updates Linux tarballs with cosign (#68053)
* add managed updates artifact signature verification

* updating signature max size to a more realistic, yet generous size

* fail teleport-update bulds when artifact verifier key is missing

* forward artifact signing key into Docker buildbox

* verify artifact signature over stream instead of pre-computed digest

* add insecure-skip-artifact-signature flag for dev builds

* renaming insecure signature flag and simplify verifier flow

* import separation for linter CI fix

* gofmt

* simplifying verifyArfifactSig function, table tests

* verify artifact signature during install, adding godoc for WithDigest

* adding staging CDN fallback

* updating isStagingCDN url check by adding helper function to check for raw vs want url equality, pr comments

* clarify ECDSA-specific digest verification comment

* initialize artifact signature verifier at construction time

* embed backup artifact signature public key for managed updates

* move teleport-update signature inputs to main.go

* removing comment

* verify staging signatures by default with explicit fallback

* update staging signature verification to trust prod artifacts

* fix test expected message error
2026-08-07 20:05:42 +00:00

308 lines
7.2 KiB
Go

/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package agent
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/gravitational/teleport/lib/autoupdate"
)
func TestNewRevisionFromDir(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
name string
dir string
rev Revision
errMatch string
}{
{
name: "version",
dir: "1.2.3",
rev: Revision{
Version: "1.2.3",
},
},
{
name: "full",
dir: "1.2.3_ent_fips",
rev: Revision{
Version: "1.2.3",
Flags: autoupdate.FlagEnterprise | autoupdate.FlagFIPS,
},
},
{
name: "ent",
dir: "1.2.3_ent",
rev: Revision{
Version: "1.2.3",
Flags: autoupdate.FlagEnterprise,
},
},
{
name: "empty",
errMatch: "missing",
},
{
name: "trailing",
dir: "1.2.3_",
errMatch: "invalid",
},
{
name: "more trailing",
dir: "1.2.3___",
errMatch: "invalid",
},
{
name: "no version",
dir: "_fips",
errMatch: "missing",
},
{
name: "fips no ent",
dir: "1.2.3_fips",
errMatch: "invalid",
},
{
name: "unknown start fips",
dir: "1.2.3_test_fips",
errMatch: "invalid",
},
{
name: "unknown start ent",
dir: "1.2.3_test_ent",
errMatch: "invalid",
},
{
name: "unknown end fips",
dir: "1.2.3_fips_test",
errMatch: "invalid",
},
{
name: "unknown end ent",
dir: "1.2.3_ent_test",
errMatch: "invalid",
},
{
name: "bad order",
dir: "1.2.3_fips_ent",
errMatch: "invalid",
},
{
name: "underscore",
dir: "_",
errMatch: "missing",
},
} {
t.Run(tt.name, func(t *testing.T) {
rev, err := NewRevisionFromDir(tt.dir)
if tt.errMatch != "" {
require.ErrorContains(t, err, tt.errMatch)
return
}
require.NoError(t, err)
require.Equal(t, tt.rev, rev)
require.Equal(t, tt.dir, rev.Dir())
})
}
}
func TestValidateConfigSpec(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
name string
config UpdateSpec
override UpdateSpec
insecureSkipSignatureVerify bool
insecureChanged bool
enableStagingSignatureVerify bool
enableStagingChanged bool
result UpdateSpec
errMatch string
}{
{
name: "overrides",
config: UpdateSpec{
Proxy: "proxy",
Path: "/path",
Group: "group",
BaseURL: "https://example.com",
},
override: UpdateSpec{
Enabled: true,
Pinned: true,
Proxy: "overrideProxy",
Path: "/overridePath",
Group: "group2",
BaseURL: "https://example.com",
},
result: UpdateSpec{
Enabled: true,
Pinned: true,
Proxy: "overrideProxy",
Path: "/overridePath",
Group: "group2",
BaseURL: "https://example.com",
},
},
{
name: "default overrides",
config: UpdateSpec{
Proxy: "proxy",
Path: "/path",
Group: "group",
BaseURL: "https://example.com",
},
override: UpdateSpec{
Proxy: "default",
Path: "default",
Group: "default",
BaseURL: "default",
},
result: UpdateSpec{
Proxy: "default",
Path: "default",
},
},
{
name: "only overrides",
override: UpdateSpec{
Enabled: true,
Pinned: true,
Proxy: "overrideProxy",
Path: "/overridePath",
Group: "group2",
BaseURL: "https://example.com",
},
result: UpdateSpec{
Enabled: true,
Pinned: true,
Proxy: "overrideProxy",
Path: "/overridePath",
Group: "group2",
BaseURL: "https://example.com",
},
},
{
name: "no overrides",
config: UpdateSpec{
Proxy: "proxy",
Path: "/path",
Group: "group",
BaseURL: "https://example.com",
},
result: UpdateSpec{
Proxy: "proxy",
Path: "/path",
Group: "group",
BaseURL: "https://example.com",
},
},
{
name: "BaseURL validation fails",
override: UpdateSpec{
BaseURL: "http://example.com",
},
errMatch: "must use TLS",
},
{
name: "insecure checksum-only mode allowed",
override: UpdateSpec{
BaseURL: "https://example.com",
},
insecureSkipSignatureVerify: true,
insecureChanged: true,
result: UpdateSpec{
BaseURL: "https://example.com",
InsecureSkipSignatureVerify: true,
},
},
{
name: "insecure checksum-only mode allowed with default base URL",
insecureSkipSignatureVerify: true,
insecureChanged: true,
result: UpdateSpec{
InsecureSkipSignatureVerify: true,
},
},
{
name: "insecure checksum-only mode can be cleared",
config: UpdateSpec{
BaseURL: "https://example.com",
InsecureSkipSignatureVerify: true,
},
insecureChanged: true,
result: UpdateSpec{
BaseURL: "https://example.com",
},
},
{
name: "enable staging signature verification can be enabled",
override: UpdateSpec{
BaseURL: "https://cdn.cloud.gravitational.io",
},
enableStagingSignatureVerify: true,
enableStagingChanged: true,
result: UpdateSpec{
BaseURL: "https://cdn.cloud.gravitational.io",
EnableStagingSignatureVerify: true,
},
},
{
name: "enable staging signature verification can be cleared",
config: UpdateSpec{
BaseURL: "https://cdn.cloud.gravitational.io",
EnableStagingSignatureVerify: true,
},
enableStagingChanged: true,
result: UpdateSpec{
BaseURL: "https://cdn.cloud.gravitational.io",
},
},
} {
t.Run(tt.name, func(t *testing.T) {
err := updateConfigSpec(&tt.config, OverrideConfig{
UpdateSpec: UpdateSpec{
Proxy: tt.override.Proxy,
Path: tt.override.Path,
Group: tt.override.Group,
BaseURL: tt.override.BaseURL,
Enabled: tt.override.Enabled,
Pinned: tt.override.Pinned,
SELinuxSSH: tt.override.SELinuxSSH,
InsecureSkipSignatureVerify: tt.insecureSkipSignatureVerify,
EnableStagingSignatureVerify: tt.enableStagingSignatureVerify,
},
InsecureSkipSignatureVerifyChanged: tt.insecureChanged,
EnableStagingSignatureVerifyChanged: tt.enableStagingChanged,
})
if tt.errMatch != "" {
require.ErrorContains(t, err, tt.errMatch)
return
}
require.NoError(t, err)
require.Equal(t, tt.result, tt.config)
})
}
}