github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/integration_test.go (about)

     1  /*
     2  Copyright 2023 Gravitational, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package types
    18  
    19  import (
    20  	"encoding/json"
    21  	"testing"
    22  
    23  	"github.com/google/uuid"
    24  	"github.com/gravitational/trace"
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"github.com/gravitational/teleport/api/defaults"
    28  )
    29  
    30  func TestIntegrationJSONMarshalCycle(t *testing.T) {
    31  	aws, err := NewIntegrationAWSOIDC(
    32  		Metadata{Name: "some-integration"},
    33  		&AWSOIDCIntegrationSpecV1{
    34  			RoleARN:     "arn:aws:iam::123456789012:role/DevTeams",
    35  			IssuerS3URI: "s3://my-bucket/my-prefix",
    36  		},
    37  	)
    38  	require.NoError(t, err)
    39  
    40  	azure, err := NewIntegrationAzureOIDC(
    41  		Metadata{Name: "some-integration"},
    42  		&AzureOIDCIntegrationSpecV1{
    43  			TenantID: "foo-bar",
    44  			ClientID: "baz-quux",
    45  		},
    46  	)
    47  	require.NoError(t, err)
    48  
    49  	allIntegrations := []*IntegrationV1{aws, azure}
    50  
    51  	for _, ig := range allIntegrations {
    52  		t.Run(ig.SubKind, func(t *testing.T) {
    53  			bs, err := json.Marshal(ig)
    54  			require.NoError(t, err)
    55  
    56  			var ig2 IntegrationV1
    57  			err = json.Unmarshal(bs, &ig2)
    58  			require.NoError(t, err)
    59  
    60  			require.Equal(t, &ig2, ig)
    61  		})
    62  	}
    63  }
    64  
    65  func TestIntegrationCheckAndSetDefaults(t *testing.T) {
    66  	noErrorFunc := func(err error) bool {
    67  		return err == nil
    68  	}
    69  
    70  	for _, tt := range []struct {
    71  		name                string
    72  		integration         func(string) (*IntegrationV1, error)
    73  		expectedIntegration func(string) *IntegrationV1
    74  		expectedErrorIs     func(error) bool
    75  	}{
    76  		{
    77  			name: "aws-oidc: valid",
    78  			integration: func(name string) (*IntegrationV1, error) {
    79  				return NewIntegrationAWSOIDC(
    80  					Metadata{
    81  						Name: name,
    82  					},
    83  					&AWSOIDCIntegrationSpecV1{
    84  						RoleARN:     "some arn role",
    85  						IssuerS3URI: "s3://my-issuer/my-prefix",
    86  					},
    87  				)
    88  			},
    89  			expectedIntegration: func(name string) *IntegrationV1 {
    90  				return &IntegrationV1{
    91  					ResourceHeader: ResourceHeader{
    92  						Kind:    KindIntegration,
    93  						SubKind: IntegrationSubKindAWSOIDC,
    94  						Version: V1,
    95  						Metadata: Metadata{
    96  							Name:      name,
    97  							Namespace: defaults.Namespace,
    98  						},
    99  					},
   100  					Spec: IntegrationSpecV1{
   101  						SubKindSpec: &IntegrationSpecV1_AWSOIDC{
   102  							AWSOIDC: &AWSOIDCIntegrationSpecV1{
   103  								RoleARN:     "some arn role",
   104  								IssuerS3URI: "s3://my-issuer/my-prefix",
   105  							},
   106  						},
   107  					},
   108  				}
   109  			},
   110  			expectedErrorIs: noErrorFunc,
   111  		},
   112  		{
   113  			name: "aws-oidc: error when subkind spec is not provided",
   114  			integration: func(name string) (*IntegrationV1, error) {
   115  				return NewIntegrationAWSOIDC(
   116  					Metadata{
   117  						Name: name,
   118  					},
   119  					nil,
   120  				)
   121  			},
   122  			expectedErrorIs: trace.IsBadParameter,
   123  		},
   124  		{
   125  			name: "aws-oidc: error when issuer is not a valid url",
   126  			integration: func(name string) (*IntegrationV1, error) {
   127  				return NewIntegrationAWSOIDC(
   128  					Metadata{
   129  						Name: name,
   130  					},
   131  					&AWSOIDCIntegrationSpecV1{
   132  						RoleARN:     "some-role",
   133  						IssuerS3URI: "not-a-url",
   134  					},
   135  				)
   136  			},
   137  			expectedErrorIs: trace.IsBadParameter,
   138  		},
   139  		{
   140  			name: "aws-oidc: issuer is not an s3 url",
   141  			integration: func(name string) (*IntegrationV1, error) {
   142  				return NewIntegrationAWSOIDC(
   143  					Metadata{
   144  						Name: name,
   145  					},
   146  					&AWSOIDCIntegrationSpecV1{
   147  						RoleARN:     "some-role",
   148  						IssuerS3URI: "http://localhost:8080",
   149  					},
   150  				)
   151  			},
   152  			expectedErrorIs: trace.IsBadParameter,
   153  		},
   154  		{
   155  			name: "aws-oidc: error when no role is provided",
   156  			integration: func(name string) (*IntegrationV1, error) {
   157  				return NewIntegrationAWSOIDC(
   158  					Metadata{
   159  						Name: name,
   160  					},
   161  					&AWSOIDCIntegrationSpecV1{},
   162  				)
   163  			},
   164  			expectedErrorIs: trace.IsBadParameter,
   165  		},
   166  		{
   167  			name: "azure-oidc: valid",
   168  			integration: func(name string) (*IntegrationV1, error) {
   169  				return NewIntegrationAzureOIDC(
   170  					Metadata{
   171  						Name: name,
   172  					},
   173  					&AzureOIDCIntegrationSpecV1{
   174  						ClientID: "baz-quux",
   175  						TenantID: "foo-bar",
   176  					},
   177  				)
   178  			},
   179  			expectedIntegration: func(name string) *IntegrationV1 {
   180  				return &IntegrationV1{
   181  					ResourceHeader: ResourceHeader{
   182  						Kind:    KindIntegration,
   183  						SubKind: IntegrationSubKindAzureOIDC,
   184  						Version: V1,
   185  						Metadata: Metadata{
   186  							Name:      name,
   187  							Namespace: defaults.Namespace,
   188  						},
   189  					},
   190  					Spec: IntegrationSpecV1{
   191  						SubKindSpec: &IntegrationSpecV1_AzureOIDC{
   192  							AzureOIDC: &AzureOIDCIntegrationSpecV1{
   193  								ClientID: "baz-quux",
   194  								TenantID: "foo-bar",
   195  							},
   196  						},
   197  					},
   198  				}
   199  			},
   200  			expectedErrorIs: noErrorFunc,
   201  		},
   202  		{
   203  			name: "azure-oidc: error when no tenant id is provided",
   204  			integration: func(name string) (*IntegrationV1, error) {
   205  				return NewIntegrationAzureOIDC(
   206  					Metadata{
   207  						Name: name,
   208  					},
   209  					&AzureOIDCIntegrationSpecV1{
   210  						ClientID: "baz-quux",
   211  					},
   212  				)
   213  			},
   214  			expectedErrorIs: trace.IsBadParameter,
   215  		},
   216  		{
   217  			name: "azure-oidc: error when no client id is provided",
   218  			integration: func(name string) (*IntegrationV1, error) {
   219  				return NewIntegrationAzureOIDC(
   220  					Metadata{
   221  						Name: name,
   222  					},
   223  					&AzureOIDCIntegrationSpecV1{
   224  						TenantID: "foo-bar",
   225  					},
   226  				)
   227  			},
   228  			expectedErrorIs: trace.IsBadParameter,
   229  		},
   230  	} {
   231  		t.Run(tt.name, func(t *testing.T) {
   232  			name := uuid.NewString()
   233  			ig, err := tt.integration(name)
   234  			require.True(t, tt.expectedErrorIs(err), "expected another error", err)
   235  			if err != nil {
   236  				return
   237  			}
   238  
   239  			require.Equal(t, tt.expectedIntegration(name), ig)
   240  			require.Contains(t, ig.String(), name)
   241  		})
   242  	}
   243  }