From d41b76635514e4a0d11196487f32c64b13d07698 Mon Sep 17 00:00:00 2001 From: Sean Trantalis Date: Thu, 14 Nov 2024 14:32:15 -0500 Subject: [PATCH] run integration tests with tls --- .github/workflows/checks.yaml | 9 +++ examples/cmd/examples.go | 5 +- opentdf-dev.yaml | 4 ++ service/rttests/rt_test.go | 121 ++++++++++++++++------------------ test/policy-service.bats | 2 +- test/service-start.bats | 10 +-- test/tdf-roundtrips.bats | 8 +++ 7 files changed, 87 insertions(+), 72 deletions(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 26f592678..b0c1602e6 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -105,9 +105,18 @@ jobs: run: ./.github/scripts/work-init.sh - run: go mod download - run: go mod verify + - name: Install mkcert + run: | + sudo apt-get install -y libnss3-tools + curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64" + chmod +x mkcert-v*-linux-amd64 + sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert - run: | .github/scripts/init-temp-keys.sh + mkcert -install + mkcert -cert-file ./keys/localhost.crt -key-file ./keys/localhost-key.pem localhost cp opentdf-dev.yaml opentdf.yaml + yq eval '.server.tls.enabled = true' -i opentdf.yaml - name: Added Trusted Certs run: | sudo chmod -R 777 ./keys diff --git a/examples/cmd/examples.go b/examples/cmd/examples.go index 94c0c885b..6eea627dc 100644 --- a/examples/cmd/examples.go +++ b/examples/cmd/examples.go @@ -2,11 +2,12 @@ package cmd import ( "fmt" - "google.golang.org/grpc/resolver" "log" "os" "strings" + "google.golang.org/grpc/resolver" + "github.com/opentdf/platform/sdk" "github.com/spf13/cobra" ) @@ -30,7 +31,7 @@ func init() { func newSDK() (*sdk.SDK, error) { resolver.SetDefaultScheme("passthrough") - opts := []sdk.Option{sdk.WithStoreCollectionHeaders(), sdk.WithInsecurePlaintextConn()} + opts := []sdk.Option{sdk.WithStoreCollectionHeaders()} if clientCredentials != "" { i := strings.Index(clientCredentials, ":") if i < 0 { diff --git a/opentdf-dev.yaml b/opentdf-dev.yaml index 4a8509647..7c1f5d2b9 100644 --- a/opentdf-dev.yaml +++ b/opentdf-dev.yaml @@ -33,6 +33,10 @@ services: email: true username: true server: + tls: + enabled: false + cert: ./keys/platform.crt + key: ./keys/platform-key.pem auth: enabled: true enforceDPoP: false diff --git a/service/rttests/rt_test.go b/service/rttests/rt_test.go index d8973e6c4..49a43737b 100644 --- a/service/rttests/rt_test.go +++ b/service/rttests/rt_test.go @@ -36,7 +36,8 @@ type TestConfig struct { var attributesToMap = []string{ "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/red", - "https://example.com/attr/cards/value/queen"} + "https://example.com/attr/cards/value/queen", +} var successAttributeSets = [][]string{ {}, @@ -45,11 +46,13 @@ var successAttributeSets = [][]string{ {"https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green"}, {"https://example.com/attr/cards/value/jack"}, {"https://example.com/attr/cards/value/queen"}, - {"https://example.com/attr/language/value/english", + { + "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green", "https://example.com/attr/cards/value/jack", - "https://example.com/attr/cards/value/queen"}, + "https://example.com/attr/cards/value/queen", + }, } var failureAttributeSets = [][]string{ @@ -57,19 +60,25 @@ var failureAttributeSets = [][]string{ {"https://example.com/attr/color/value/blue"}, {"https://example.com/attr/color/value/blue", "https://example.com/attr/color/value/green"}, {"https://example.com/attr/cards/value/king"}, - {"https://example.com/attr/language/value/english", + { + "https://example.com/attr/language/value/english", "https://example.com/attr/language/value/french", "https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green", - "https://example.com/attr/cards/value/queen"}, - {"https://example.com/attr/language/value/english", + "https://example.com/attr/cards/value/queen", + }, + { + "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/blue", "https://example.com/attr/color/value/green", - "https://example.com/attr/cards/value/queen"}, - {"https://example.com/attr/language/value/english", + "https://example.com/attr/cards/value/queen", + }, + { + "https://example.com/attr/language/value/english", "https://example.com/attr/color/value/red", "https://example.com/attr/color/value/green", - "https://example.com/attr/cards/value/king"}, + "https://example.com/attr/cards/value/king", + }, } func newTestConfig() TestConfig { @@ -91,13 +100,25 @@ func Test_RoundTrips(t *testing.T) { type RoundtripSuite struct { suite.Suite TestConfig + client *sdk.SDK } func (s *RoundtripSuite) SetupSuite() { s.TestConfig = newTestConfig() slog.Info("Test config", "", s.TestConfig) - err := s.CreateTestData() + opts := []sdk.Option{} + if os.Getenv("TLS_ENABLED") == "" { + opts = append(opts, sdk.WithInsecurePlaintextConn()) + } + + opts = append(opts, sdk.WithClientCredentials(s.TestConfig.ClientID, s.TestConfig.ClientSecret, nil)) + + sdk, err := sdk.New(s.TestConfig.PlatformEndpoint, opts...) + s.Require().NoError(err) + s.client = sdk + + err = s.CreateTestData() s.Require().NoError(err) } @@ -108,9 +129,9 @@ func (s *RoundtripSuite) Tests() { s.Run(n, func() { filename := fmt.Sprintf("test-success-%d.tdf", i) plaintext := "Running a roundtrip test!" - err := encrypt(&s.TestConfig, plaintext, attributes, filename) + err := encrypt(s.client, s.TestConfig, plaintext, attributes, filename) s.Require().NoError(err) - err = decrypt(&s.TestConfig, filename, plaintext) + err = decrypt(s.client, filename, plaintext) s.NoError(err) }) } @@ -121,30 +142,21 @@ func (s *RoundtripSuite) Tests() { s.Run(n, func() { filename := fmt.Sprintf("test-failure-%d.tdf", i) plaintext := "Running a roundtrip test!" - err := encrypt(&s.TestConfig, plaintext, attributes, filename) + err := encrypt(s.client, s.TestConfig, plaintext, attributes, filename) s.Require().NoError(err) - err = decrypt(&s.TestConfig, filename, plaintext) + err = decrypt(s.client, filename, plaintext) s.ErrorContains(err, "PermissionDenied") }) } } func (s *RoundtripSuite) CreateTestData() error { - sdk, err := sdk.New(s.TestConfig.PlatformEndpoint, - sdk.WithInsecurePlaintextConn(), - sdk.WithClientCredentials(s.TestConfig.ClientID, - s.TestConfig.ClientSecret, nil), - ) - if err != nil { - slog.Error("could not connect", slog.String("error", err.Error())) - return err - } - defer sdk.Close() + client := s.client // create namespace example.com var exampleNamespace *policy.Namespace slog.Info("listing namespaces") - listResp, err := sdk.Namespaces.ListNamespaces(context.Background(), &namespaces.ListNamespacesRequest{}) + listResp, err := client.Namespaces.ListNamespaces(context.Background(), &namespaces.ListNamespacesRequest{}) if err != nil { return err } @@ -158,7 +170,7 @@ func (s *RoundtripSuite) CreateTestData() error { if exampleNamespace == nil { slog.Info("creating new namespace") - resp, err := sdk.Namespaces.CreateNamespace(context.Background(), &namespaces.CreateNamespaceRequest{ + resp, err := client.Namespaces.CreateNamespace(context.Background(), &namespaces.CreateNamespaceRequest{ Name: "example.com", }) if err != nil { @@ -171,7 +183,7 @@ func (s *RoundtripSuite) CreateTestData() error { // Create the attributes slog.Info("creating attribute language with allOf rule") - _, err = sdk.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ + _, err = client.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ Name: "language", NamespaceId: exampleNamespace.GetId(), Rule: *policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF.Enum(), @@ -193,7 +205,7 @@ func (s *RoundtripSuite) CreateTestData() error { } slog.Info("creating attribute color with anyOf rule") - _, err = sdk.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ + _, err = client.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ Name: "color", NamespaceId: exampleNamespace.GetId(), Rule: *policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF.Enum(), @@ -215,7 +227,7 @@ func (s *RoundtripSuite) CreateTestData() error { } slog.Info("creating attribute cards with hierarchy rule") - _, err = sdk.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ + _, err = client.Attributes.CreateAttribute(context.Background(), &attributes.CreateAttributeRequest{ Name: "cards", NamespaceId: exampleNamespace.GetId(), Rule: *policy.AttributeRuleTypeEnum_ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY.Enum(), @@ -238,7 +250,7 @@ func (s *RoundtripSuite) CreateTestData() error { slog.Info("##################################\n#######################################") - allAttr, err := sdk.Attributes.ListAttributes(context.Background(), &attributes.ListAttributesRequest{}) + allAttr, err := client.Attributes.ListAttributes(context.Background(), &attributes.ListAttributesRequest{}) if err != nil { slog.Error("could not list attributes", slog.String("error", err.Error())) return err @@ -249,7 +261,7 @@ func (s *RoundtripSuite) CreateTestData() error { // get the attribute ids for the values were mapping to the client var attributeValueIDs []string - fqnResp, err := sdk.Attributes.GetAttributeValuesByFqns(context.Background(), &attributes.GetAttributeValuesByFqnsRequest{ + fqnResp, err := client.Attributes.GetAttributeValuesByFqns(context.Background(), &attributes.GetAttributeValuesByFqnsRequest{ Fqns: attributesToMap, WithValue: &policy.AttributeValueSelector{}, }) @@ -264,11 +276,12 @@ func (s *RoundtripSuite) CreateTestData() error { // create subject mappings slog.Info("creating subject mappings for client " + s.TestConfig.ClientID) for _, attributeID := range attributeValueIDs { - _, err = sdk.SubjectMapping.CreateSubjectMapping(context.Background(), &subjectmapping.CreateSubjectMappingRequest{ + _, err = client.SubjectMapping.CreateSubjectMapping(context.Background(), &subjectmapping.CreateSubjectMappingRequest{ AttributeValueId: attributeID, - Actions: []*policy.Action{{Value: &policy.Action_Standard{ - Standard: policy.Action_STANDARD_ACTION_DECRYPT, - }}, + Actions: []*policy.Action{ + {Value: &policy.Action_Standard{ + Standard: policy.Action_STANDARD_ACTION_DECRYPT, + }}, {Value: &policy.Action_Standard{ Standard: policy.Action_STANDARD_ACTION_TRANSMIT, }}, @@ -276,11 +289,12 @@ func (s *RoundtripSuite) CreateTestData() error { NewSubjectConditionSet: &subjectmapping.SubjectConditionSetCreate{ SubjectSets: []*policy.SubjectSet{ {ConditionGroups: []*policy.ConditionGroup{ - {Conditions: []*policy.Condition{{ - SubjectExternalSelectorValue: ".clientId", - Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, - SubjectExternalValues: []string{s.TestConfig.ClientID}, - }}, + { + Conditions: []*policy.Condition{{ + SubjectExternalSelectorValue: ".clientId", + Operator: policy.SubjectMappingOperatorEnum_SUBJECT_MAPPING_OPERATOR_ENUM_IN, + SubjectExternalValues: []string{s.TestConfig.ClientID}, + }}, BooleanOperator: policy.ConditionBooleanTypeEnum_CONDITION_BOOLEAN_TYPE_ENUM_AND, }, }}, @@ -299,7 +313,7 @@ func (s *RoundtripSuite) CreateTestData() error { } } - allSubMaps, err := sdk.SubjectMapping.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{}) + allSubMaps, err := client.SubjectMapping.ListSubjectMappings(context.Background(), &subjectmapping.ListSubjectMappingsRequest{}) if err != nil { slog.Error("could not list subject mappings", slog.String("error", err.Error())) return err @@ -309,20 +323,9 @@ func (s *RoundtripSuite) CreateTestData() error { return nil } -func encrypt(testConfig *TestConfig, plaintext string, attributes []string, filename string) error { +func encrypt(client *sdk.SDK, testConfig TestConfig, plaintext string, attributes []string, filename string) error { strReader := strings.NewReader(plaintext) - // Create new offline client - client, err := sdk.New(testConfig.PlatformEndpoint, - sdk.WithInsecurePlaintextConn(), - sdk.WithClientCredentials(testConfig.ClientID, - testConfig.ClientSecret, nil), - sdk.WithTokenEndpoint(testConfig.TokenEndpoint), - ) - if err != nil { - return err - } - tdfFile, err := os.Create(filename) if err != nil { return err @@ -344,17 +347,7 @@ func encrypt(testConfig *TestConfig, plaintext string, attributes []string, file return nil } -func decrypt(testConfig *TestConfig, tdfFile string, plaintext string) error { - // Create new client - client, err := sdk.New(testConfig.PlatformEndpoint, - sdk.WithInsecurePlaintextConn(), - sdk.WithClientCredentials(testConfig.ClientID, - testConfig.ClientSecret, nil), - sdk.WithTokenEndpoint(testConfig.TokenEndpoint), - ) - if err != nil { - return err - } +func decrypt(client *sdk.SDK, tdfFile string, plaintext string) error { file, err := os.Open(tdfFile) if err != nil { return err diff --git a/test/policy-service.bats b/test/policy-service.bats index f08c042f1..47908d0c1 100755 --- a/test/policy-service.bats +++ b/test/policy-service.bats @@ -3,7 +3,7 @@ # Tests for policy service administration @test "gRPC: lists attributes" { - run grpcurl -plaintext "localhost:8080" list + run grpcurl "localhost:8080" list echo "$output" [ $status = 0 ] [[ $output = *grpc.health.v1.Health* ]] diff --git a/test/service-start.bats b/test/service-start.bats index 44febc431..34c834450 100755 --- a/test/service-start.bats +++ b/test/service-start.bats @@ -3,14 +3,14 @@ # Tests for validating that the system is nominally running @test "gRPC: health check is healthy" { - run grpcurl -plaintext "localhost:8080" "grpc.health.v1.Health.Check" + run grpcurl "localhost:8080" "grpc.health.v1.Health.Check" echo "$output" [ $status = 0 ] [ $(jq -r .status <<<"${output}") = SERVING ] } @test "gRPC: reports a public key" { - run grpcurl -plaintext "localhost:8080" "kas.AccessService/PublicKey" + run grpcurl "localhost:8080" "kas.AccessService/PublicKey" echo "$output" # Is public key @@ -25,7 +25,7 @@ } @test "REST: new public key endpoint (no algorithm)" { - run curl -s --show-error --fail-with-body --insecure "localhost:8080/kas/v2/kas_public_key" + run curl -s --show-error --fail-with-body "localhost:8080/kas/v2/kas_public_key" echo "output=$output" p=$(jq -r .publicKey <<<"${output}") @@ -40,7 +40,7 @@ } @test "REST: new public key endpoint (ec)" { - run curl -s --show-error --fail-with-body --insecure "localhost:8080/kas/v2/kas_public_key?algorithm=ec:secp256r1" + run curl -s --show-error --fail-with-body "localhost:8080/kas/v2/kas_public_key?algorithm=ec:secp256r1" echo "$output" # Is public key @@ -61,7 +61,7 @@ } @test "gRPC: public key endpoint (unknown algorithm)" { - run grpcurl -d '{"algorithm":"invalid"}' -plaintext "localhost:8080" "kas.AccessService/PublicKey" + run grpcurl -d '{"algorithm":"invalid"}' "localhost:8080" "kas.AccessService/PublicKey" echo "$output" [[ $output = *NotFound* ]] } diff --git a/test/tdf-roundtrips.bats b/test/tdf-roundtrips.bats index af28f751f..d9ec4216f 100755 --- a/test/tdf-roundtrips.bats +++ b/test/tdf-roundtrips.bats @@ -158,6 +158,10 @@ services: realm: "opentdf" legacykeycloak: true server: + tls: + enabled: true + cert: ./keys/platform.crt + key: ./keys/platform-key.pem auth: enabled: true enforceDPoP: false @@ -229,6 +233,10 @@ services: realm: "opentdf" legacykeycloak: true server: + tls: + enabled: true + cert: ./keys/platform.crt + key: ./keys/platform-key.pem auth: enabled: true enforceDPoP: false