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 }