Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/backend/dynamo/dynamodbbk.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ import (
"github.com/gravitational/teleport/api/utils"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/modules"
awsmetrics "github.com/gravitational/teleport/lib/observability/metrics/aws"
dynamometrics "github.com/gravitational/teleport/lib/observability/metrics/dynamo"
awsutils "github.com/gravitational/teleport/lib/utils/aws"
"github.com/gravitational/teleport/lib/utils/aws/endpoint"
)

Expand Down Expand Up @@ -293,7 +293,7 @@ func New(ctx context.Context, params backend.Params) (*Backend, error) {
// FIPS settings are applied on the individual service instead of the aws config,
// as DynamoDB Streams and Application Auto Scaling do not yet have FIPS endpoints in non-GovCloud.
// See also: https://aws.amazon.com/compliance/fips/#FIPS_Endpoints_by_Service
if modules.GetModules().IsBoringBinary() {
if awsutils.UseFIPSForDynamoDB() {
dynamoOpts = append(dynamoOpts, func(o *dynamodb.Options) {
o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateEnabled
})
Expand Down
4 changes: 2 additions & 2 deletions lib/events/dynamoevents/dynamoevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ import (
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/modules"
awsmetrics "github.com/gravitational/teleport/lib/observability/metrics/aws"
dynamometrics "github.com/gravitational/teleport/lib/observability/metrics/dynamo"
"github.com/gravitational/teleport/lib/utils"
awsutils "github.com/gravitational/teleport/lib/utils/aws"
"github.com/gravitational/teleport/lib/utils/aws/endpoint"
)

Expand Down Expand Up @@ -330,7 +330,7 @@ func New(ctx context.Context, cfg Config) (*Log, error) {
// FIPS settings are applied on the individual service instead of the aws config,
// as DynamoDB Streams and Application Auto Scaling do not yet have FIPS endpoints in non-GovCloud.
// See also: https://aws.amazon.com/compliance/fips/#FIPS_Endpoints_by_Service
if modules.GetModules().IsBoringBinary() && cfg.UseFIPSEndpoint == types.ClusterAuditConfigSpecV2_FIPS_ENABLED {
if awsutils.UseFIPSForDynamoDB() && cfg.UseFIPSEndpoint == types.ClusterAuditConfigSpecV2_FIPS_ENABLED {
Comment thread
codingllama marked this conversation as resolved.
dynamoOpts = append(dynamoOpts, func(o *dynamodb.Options) {
o.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateEnabled
})
Expand Down
32 changes: 23 additions & 9 deletions lib/events/dynamoevents/dynamoevents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/session"
"github.com/gravitational/teleport/lib/utils"
awsutils "github.com/gravitational/teleport/lib/utils/aws"
)

const dynamoDBLargeQueryRetries int = 10
Expand Down Expand Up @@ -608,12 +609,23 @@ func randStringAlpha(n int) string {

func TestEndpoints(t *testing.T) {
tests := []struct {
name string
fips bool
name string
fips bool
env map[string]string
wantFIPSError bool
}{
{
name: "fips",
name: "fips",
fips: true,
wantFIPSError: true,
},
{
name: "fips with env skip",
fips: true,
env: map[string]string{
awsutils.EnvVarDisableDynamoDBFIPS: "yes",
},
wantFIPSError: false,
},
{
name: "without fips",
Expand All @@ -631,6 +643,10 @@ func TestEndpoints(t *testing.T) {
})
}

for k, v := range tt.env {
t.Setenv(k, v)
}

mux := http.NewServeMux()
mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTeapot)
Expand All @@ -655,15 +671,13 @@ func TestEndpoints(t *testing.T) {
})
// FIPS mode should fail because it is a violation to enable FIPS
// while also setting a custom endpoint.
if tt.fips {
assert.Error(t, err)
require.ErrorContains(t, err, "FIPS")
if tt.wantFIPSError {
assert.ErrorContains(t, err, "FIPS")
return
}

assert.Error(t, err)
assert.Nil(t, b)
require.ErrorContains(t, err, fmt.Sprintf("StatusCode: %d", http.StatusTeapot))
assert.ErrorContains(t, err, fmt.Sprintf("StatusCode: %d", http.StatusTeapot))
assert.Nil(t, b, "backend not nil")
})
}
}
Expand Down
49 changes: 49 additions & 0 deletions lib/utils/aws/dynamo_fips.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Teleport
// Copyright (C) 2025 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 aws

import (
"os"
"strconv"

"github.com/gravitational/teleport/lib/modules"
)

// EnvVarDisableDynamoDBFIPS holds the name of the environment variable that
// disables FIPS for DynamoDB access in builds where FIPS would otherwise be
// required.
const EnvVarDisableDynamoDBFIPS = "TELEPORT_UNSTABLE_DISABLE_DYNAMODB_FIPS"

// UseFIPSForDynamoDB is a DynamoDB-specific check that builds on
// [modules.Modules.IsBoringBinary].
//
// FIPS is enabled by default for boring/FIPS teleport binaries, unless the
// TELEPORT_UNSTABLE_DISABLE_DYNAMODB_FIPS env variable is set to "yes" (or an
// equivalent boolean).
func UseFIPSForDynamoDB() bool {
// If the skip toggle is set we don't use FIPS DynamoDB.
if val := os.Getenv(EnvVarDisableDynamoDBFIPS); val != "" {
if val == "yes" {
return false
}
if b, _ := strconv.ParseBool(val); b {
return false
}
}

return modules.GetModules().IsBoringBinary()
}
82 changes: 82 additions & 0 deletions lib/utils/aws/dynamo_fips_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Teleport
// Copyright (C) 2025 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 aws_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/gravitational/teleport/lib/modules"
awsutils "github.com/gravitational/teleport/lib/utils/aws"
)

func TestUseFIPSForDynamoDB(t *testing.T) {
// Don't t.Parallel(), uses both modules.SetTestModules and t.Setenv.

tests := []struct {
name string
fips bool
env map[string]string
want bool
}{
{
name: "non-FIPS binary",
want: false,
},
{
name: "non-FIPS binary with env skip",
env: map[string]string{
awsutils.EnvVarDisableDynamoDBFIPS: "yes",
},
want: false,
},
{
name: "FIPS binary",
fips: true,
want: true,
},
{
name: "FIPS binary with env skip",
fips: true,
env: map[string]string{
awsutils.EnvVarDisableDynamoDBFIPS: "yes",
},
want: false,
},
{
name: "FIPS binary with env skip (strconv.ParseBool)",
fips: true,
env: map[string]string{
awsutils.EnvVarDisableDynamoDBFIPS: "1",
},
want: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
modules.SetTestModules(t, &modules.TestModules{
FIPS: test.fips,
})
for k, v := range test.env {
t.Setenv(k, v)
}

assert.Equal(t, test.want, awsutils.UseFIPSForDynamoDB(), "UseFIPSForDynamoDB mismatch")
})
}
}