github.com/kiali/kiali@v1.84.0/business/checkers/authorization/no_host_checker_test.go (about) 1 package authorization 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 networking_v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" 8 security_v1beta "istio.io/client-go/pkg/apis/security/v1beta1" 9 10 "github.com/kiali/kiali/kubernetes" 11 "github.com/kiali/kiali/models" 12 "github.com/kiali/kiali/tests/data" 13 "github.com/kiali/kiali/tests/testutils/validations" 14 ) 15 16 func TestPresentService(t *testing.T) { 17 assert := assert.New(t) 18 19 registryService1 := data.CreateFakeRegistryServices("details.bookinfo.svc.cluster.local", "bookinfo", "*") 20 registryService2 := data.CreateFakeRegistryServices("reviews.bookinfo.svc.cluster.local", "bookinfo", "*") 21 22 validations, valid := NoHostChecker{ 23 AuthorizationPolicy: authPolicyWithHost([]string{"details", "reviews"}), 24 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 25 ServiceEntries: map[string][]string{}, 26 RegistryServices: append(registryService1, registryService2...), 27 PolicyAllowAny: true, 28 }.Check() 29 30 // Well configured object 31 assert.True(valid) 32 assert.Empty(validations) 33 } 34 35 func TestNonExistingService(t *testing.T) { 36 assert := assert.New(t) 37 38 registryService1 := data.CreateFakeRegistryServices("details.bookinfo.svc.cluster.local", "bookinfo", "*") 39 registryService2 := data.CreateFakeRegistryServices("reviews.bookinfo.svc.cluster.local", "bookinfo", "*") 40 41 vals, valid := NoHostChecker{ 42 AuthorizationPolicy: authPolicyWithHost([]string{"details", "wrong"}), 43 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 44 ServiceEntries: map[string][]string{}, 45 RegistryServices: append(registryService1, registryService2...), 46 PolicyAllowAny: true, 47 }.Check() 48 49 // Wrong host is not present 50 assert.False(valid) 51 assert.NotEmpty(vals) 52 assert.Len(vals, 1) 53 assert.Equal(models.WarningSeverity, vals[0].Severity) 54 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 55 assert.Equal("spec/rules[0]/to[0]/operation/hosts[1]", vals[0].Path) 56 } 57 58 func TestWildcardHost(t *testing.T) { 59 assert := assert.New(t) 60 61 registryService1 := data.CreateFakeRegistryServices("details.bookinfo.svc.cluster.local", "bookinfo", "*") 62 registryService2 := data.CreateFakeRegistryServices("reviews.bookinfo.svc.cluster.local", "bookinfo", "*") 63 64 vals, valid := NoHostChecker{ 65 AuthorizationPolicy: authPolicyWithHost([]string{"*", "*.bookinfo", "*.bookinfo.svc.cluster.local"}), 66 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 67 ServiceEntries: map[string][]string{}, 68 RegistryServices: append(registryService1, registryService2...), 69 }.Check() 70 71 // Well configured object 72 assert.True(valid) 73 assert.Empty(vals) 74 } 75 76 func TestWildcardHostOutsideNamespace(t *testing.T) { 77 assert := assert.New(t) 78 79 registryService1 := data.CreateFakeRegistryServices("details.bookinfo.svc.cluster.local", "bookinfo", "*") 80 registryService2 := data.CreateFakeRegistryServices("reviews.bookinfo.svc.cluster.local", "bookinfo", "*") 81 82 vals, valid := NoHostChecker{ 83 AuthorizationPolicy: authPolicyWithHost([]string{"*.outside", "*.outside.svc.cluster.local"}), 84 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 85 ServiceEntries: map[string][]string{}, 86 RegistryServices: append(registryService1, registryService2...), 87 }.Check() 88 89 assert.False(valid) 90 assert.NotEmpty(vals) 91 assert.Len(vals, 2) 92 assert.Equal(models.ErrorSeverity, vals[0].Severity) 93 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 94 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 95 assert.Equal(models.ErrorSeverity, vals[1].Severity) 96 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[1])) 97 assert.Equal("spec/rules[0]/to[0]/operation/hosts[1]", vals[1].Path) 98 } 99 100 func TestServiceEntryPresent(t *testing.T) { 101 assert := assert.New(t) 102 103 serviceEntry := data.CreateExternalServiceEntry() 104 105 validations, valid := NoHostChecker{ 106 AuthorizationPolicy: authPolicyWithHost([]string{"wikipedia.org"}), 107 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 108 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 109 }.Check() 110 111 // Well configured object 112 assert.True(valid) 113 assert.Empty(validations) 114 } 115 116 func TestExportedInternalServiceEntryPresent(t *testing.T) { 117 assert := assert.New(t) 118 119 serviceEntry := data.CreateEmptyMeshInternalServiceEntry("details-se", "bookinfo3", []string{"details.bookinfo2.svc.cluster.local"}) 120 121 validations, valid := NoHostChecker{ 122 AuthorizationPolicy: authPolicyWithHost([]string{"details.bookinfo2.svc.cluster.local"}), 123 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 124 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 125 }.Check() 126 127 // Well configured object 128 assert.True(valid) 129 assert.Empty(validations) 130 } 131 132 func TestExportedExternalServiceEntryPresent(t *testing.T) { 133 assert := assert.New(t) 134 135 serviceEntry := data.CreateEmptyMeshExternalServiceEntry("details-se", "bookinfo3", []string{"www.myhost.com"}) 136 137 validations, valid := NoHostChecker{ 138 AuthorizationPolicy: authPolicyWithHost([]string{"www.myhost.com"}), 139 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 140 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 141 }.Check() 142 143 // Well configured object 144 assert.True(valid) 145 assert.Empty(validations) 146 } 147 148 func TestExportedExternalServiceEntryFail(t *testing.T) { 149 assert := assert.New(t) 150 151 serviceEntry := data.CreateEmptyMeshExternalServiceEntry("details-se", "bookinfo3", []string{"www.myhost.com"}) 152 153 vals, valid := NoHostChecker{ 154 AuthorizationPolicy: authPolicyWithHost([]string{"www.wrong.com"}), 155 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 156 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 157 }.Check() 158 159 // www.wrong.com host is not present 160 assert.False(valid) 161 assert.NotEmpty(vals) 162 assert.Len(vals, 1) 163 assert.Equal(models.ErrorSeverity, vals[0].Severity) 164 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 165 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 166 } 167 168 func TestWildcardExportedInternalServiceEntryPresent(t *testing.T) { 169 assert := assert.New(t) 170 171 serviceEntry := data.CreateEmptyMeshInternalServiceEntry("details-se", "bookinfo3", []string{"*.bookinfo2.svc.cluster.local"}) 172 173 validations, valid := NoHostChecker{ 174 AuthorizationPolicy: authPolicyWithHost([]string{"details.bookinfo2.svc.cluster.local"}), 175 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 176 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 177 }.Check() 178 179 // Well configured object 180 assert.True(valid) 181 assert.Empty(validations) 182 } 183 184 func TestWildcardExportedInternalServiceEntryFail(t *testing.T) { 185 assert := assert.New(t) 186 187 serviceEntry := data.CreateEmptyMeshInternalServiceEntry("details-se", "bookinfo3", []string{"details.bookinfo2.svc.cluster.local"}) 188 189 vals, valid := NoHostChecker{ 190 AuthorizationPolicy: authPolicyWithHost([]string{"details.bookinfo3.svc.cluster.local"}), 191 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 192 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 193 }.Check() 194 195 // details.bookinfo3.svc.cluster.local host is not present 196 assert.False(valid) 197 assert.NotEmpty(vals) 198 assert.Len(vals, 1) 199 assert.Equal(models.ErrorSeverity, vals[0].Severity) 200 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 201 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 202 } 203 204 func TestExportedNonFQDNInternalServiceEntryFail(t *testing.T) { 205 assert := assert.New(t) 206 207 serviceEntry := data.CreateEmptyMeshInternalServiceEntry("details-se", "bookinfo3", []string{"details"}) 208 209 vals, valid := NoHostChecker{ 210 AuthorizationPolicy: authPolicyWithHost([]string{"details.bookinfo2.svc.cluster.local"}), 211 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 212 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 213 }.Check() 214 215 // details.bookinfo2.svc.cluster.local host is not present 216 assert.False(valid) 217 assert.NotEmpty(vals) 218 assert.Len(vals, 1) 219 assert.Equal(models.ErrorSeverity, vals[0].Severity) 220 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 221 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 222 } 223 224 func TestServiceEntryNotPresent(t *testing.T) { 225 assert := assert.New(t) 226 227 serviceEntry := data.CreateExternalServiceEntry() 228 vals, valid := NoHostChecker{ 229 AuthorizationPolicy: authPolicyWithHost([]string{"wrong.org"}), 230 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 231 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 232 }.Check() 233 234 // Wrong.org host is not present 235 assert.False(valid) 236 assert.NotEmpty(vals) 237 assert.Len(vals, 1) 238 assert.Equal(models.ErrorSeverity, vals[0].Severity) 239 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 240 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 241 } 242 243 func TestExportedInternalServiceEntryNotPresent(t *testing.T) { 244 assert := assert.New(t) 245 246 serviceEntry := data.CreateEmptyMeshInternalServiceEntry("details-se", "bookinfo3", []string{"details.bookinfo2.svc.cluster.local"}) 247 vals, valid := NoHostChecker{ 248 AuthorizationPolicy: authPolicyWithHost([]string{"wrong.bookinfo2.svc.cluster.local"}), 249 Namespaces: models.Namespaces{models.Namespace{Name: "bookinfo"}, models.Namespace{Name: "bookinfo2"}, models.Namespace{Name: "bookinfo3"}}, 250 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{serviceEntry}), 251 }.Check() 252 253 // Wrong.org host is not present 254 assert.False(valid) 255 assert.NotEmpty(vals) 256 assert.Len(vals, 1) 257 assert.Equal(models.ErrorSeverity, vals[0].Severity) 258 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 259 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 260 } 261 262 func TestVirtualServicePresent(t *testing.T) { 263 assert := assert.New(t) 264 265 virtualService := *data.CreateEmptyVirtualService("foo-dev", "foo", []string{"foo-dev.example.com"}) 266 validations, valid := NoHostChecker{ 267 AuthorizationPolicy: authPolicyWithHost([]string{"foo-dev.example.com"}), 268 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 269 ServiceEntries: map[string][]string{}, 270 VirtualServices: []*networking_v1beta1.VirtualService{&virtualService}, 271 }.Check() 272 273 assert.True(valid) 274 assert.Empty(validations) 275 } 276 277 func TestVirtualServiceNotPresent(t *testing.T) { 278 assert := assert.New(t) 279 280 virtualService := *data.CreateEmptyVirtualService("foo-dev", "foo", []string{"foo-dev.example.com"}) 281 vals, valid := NoHostChecker{ 282 AuthorizationPolicy: authPolicyWithHost([]string{"foo-bogus.example.com"}), 283 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 284 ServiceEntries: map[string][]string{}, 285 VirtualServices: []*networking_v1beta1.VirtualService{&virtualService}, 286 }.Check() 287 288 // Wrong.org host is not present 289 assert.False(valid) 290 assert.NotEmpty(vals) 291 assert.Len(vals, 1) 292 assert.Equal(models.ErrorSeverity, vals[0].Severity) 293 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 294 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 295 } 296 297 func TestWildcardServiceEntryHost(t *testing.T) { 298 assert := assert.New(t) 299 300 serviceEntry := *data.CreateEmptyMeshExternalServiceEntry("googlecard", "google", []string{"*.google.com"}) 301 302 vals, valid := NoHostChecker{ 303 AuthorizationPolicy: authPolicyWithHost([]string{"maps.google.com"}), 304 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 305 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{&serviceEntry}), 306 }.Check() 307 308 // Well configured object 309 assert.True(valid) 310 assert.Empty(vals) 311 312 // Not matching 313 vals, valid = NoHostChecker{ 314 AuthorizationPolicy: authPolicyWithHost([]string{"maps.apple.com"}), 315 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 316 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{&serviceEntry}), 317 PolicyAllowAny: true, 318 }.Check() 319 320 // apple.com host is not present 321 assert.False(valid) 322 assert.NotEmpty(vals) 323 assert.Len(vals, 1) 324 assert.Equal(models.WarningSeverity, vals[0].Severity) 325 assert.NoError(validations.ConfirmIstioCheckMessage("authorizationpolicy.nodest.matchingregistry", vals[0])) 326 assert.Equal("spec/rules[0]/to[0]/operation/hosts[0]", vals[0].Path) 327 } 328 329 func authPolicyWithHost(hostList []string) *security_v1beta.AuthorizationPolicy { 330 methods := []string{"GET", "PUT", "PATCH"} 331 nss := []string{"bookinfo"} 332 selector := map[string]string{"app": "details", "version": "v1"} 333 return data.CreateAuthorizationPolicy(nss, methods, hostList, selector) 334 } 335 336 func TestValidServiceRegistry(t *testing.T) { 337 assert := assert.New(t) 338 339 validations, valid := NoHostChecker{ 340 AuthorizationPolicy: authPolicyWithHost([]string{"ratings.mesh2-bookinfo.svc.mesh1-imports.local"}), 341 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 342 }.Check() 343 344 assert.False(valid) 345 assert.NotEmpty(validations) 346 347 registryService := data.CreateFakeRegistryServices("ratings.mesh2-bookinfo.svc.mesh1-imports.local", "bookinfo", "*") 348 349 validations, valid = NoHostChecker{ 350 AuthorizationPolicy: authPolicyWithHost([]string{"ratings.mesh2-bookinfo.svc.mesh1-imports.local"}), 351 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 352 RegistryServices: registryService, 353 }.Check() 354 355 assert.True(valid) 356 assert.Empty(validations) 357 358 registryService = data.CreateFakeRegistryServices("ratings2.mesh2-bookinfo.svc.mesh1-imports.local", "bookinfo", "*") 359 360 validations, valid = NoHostChecker{ 361 AuthorizationPolicy: authPolicyWithHost([]string{"ratings.mesh2-bookinfo.svc.mesh1-imports.local"}), 362 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 363 RegistryServices: registryService, 364 }.Check() 365 366 assert.False(valid) 367 assert.NotEmpty(validations) 368 369 registryService = data.CreateFakeRegistryServices("ratings.bookinfo.svc.cluster.local", "bookinfo", "*") 370 371 validations, valid = NoHostChecker{ 372 AuthorizationPolicy: authPolicyWithHost([]string{"ratings.bookinfo.svc.cluster.local"}), 373 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 374 RegistryServices: registryService, 375 }.Check() 376 377 assert.True(valid) 378 assert.Empty(validations) 379 380 registryService = data.CreateFakeRegistryServices("ratings.bookinfo.svc.cluster.local", "bookinfo", "*") 381 382 validations, valid = NoHostChecker{ 383 AuthorizationPolicy: authPolicyWithHost([]string{"ratings2.bookinfo.svc.cluster.local"}), 384 Namespaces: models.Namespaces{models.Namespace{Name: "outside"}, models.Namespace{Name: "bookinfo"}}, 385 RegistryServices: registryService, 386 }.Check() 387 388 assert.False(valid) 389 assert.NotEmpty(validations) 390 }