Skip to content
Open
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ assets/credhub-enabled-app/.gradle
bin/ginkgo
.vs
assets/nora/Nora/obj
.worktrees
89 changes: 89 additions & 0 deletions assets/proxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func main() {
mux := http.NewServeMux()
mux.HandleFunc("/proxy/", proxyHandler)
mux.HandleFunc("/https_proxy/", httpsProxyHandler)
mux.HandleFunc("/mtls_proxy/", mtlsProxyHandler)
mux.HandleFunc("/headers", headersHandler)
mux.HandleFunc("/", infoHandler(systemPort))

server := &http.Server{
Expand Down Expand Up @@ -91,6 +93,93 @@ func handleRequest(destination string, resp http.ResponseWriter, req *http.Reque
_, _ = resp.Write(readBytes)
}

func headersHandler(resp http.ResponseWriter, req *http.Request) {
headers := make(map[string]string)
for name, values := range req.Header {
headers[name] = strings.Join(values, ", ")
}
resp.Header().Set("Content-Type", "application/json")
json.NewEncoder(resp).Encode(headers)
}

func mtlsProxyHandler(resp http.ResponseWriter, req *http.Request) {
destination := strings.TrimPrefix(req.URL.Path, "/mtls_proxy/")
destination = fmt.Sprintf("https://%s", destination)

certFile := os.Getenv("CF_INSTANCE_CERT")
keyFile := os.Getenv("CF_INSTANCE_KEY")
if certFile == "" || keyFile == "" {
resp.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(resp).Encode(map[string]interface{}{
"status": "error",
"status_code": 500,
"error": "CF_INSTANCE_CERT or CF_INSTANCE_KEY not set",
})
return
}

cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
resp.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(resp).Encode(map[string]interface{}{
"status": "error",
"status_code": 500,
"error": fmt.Sprintf("failed to load client cert: %s", err),
})
return
}

client := &http.Client{
Transport: &http.Transport{
DisableKeepAlives: true,
Dial: (&net.Dialer{
Timeout: 10 * time.Second,
KeepAlive: 0,
}).Dial,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{cert},
},
},
}

getResp, err := client.Get(destination)
if err != nil {
resp.Header().Set("Content-Type", "application/json")
json.NewEncoder(resp).Encode(map[string]interface{}{
"status": "error",
"status_code": 0,
"error": fmt.Sprintf("request failed: %s", err),
})
return
}
defer getResp.Body.Close()

body, err := io.ReadAll(getResp.Body)
if err != nil {
resp.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(resp).Encode(map[string]interface{}{
"status": "error",
"status_code": 0,
"error": fmt.Sprintf("read body failed: %s", err),
})
return
}

respHeaders := make(map[string]string)
for name, values := range getResp.Header {
respHeaders[name] = strings.Join(values, ", ")
}

resp.Header().Set("Content-Type", "application/json")
json.NewEncoder(resp).Encode(map[string]interface{}{
"status": "success",
"status_code": getResp.StatusCode,
"body": string(body),
"headers": respHeaders,
})
}

var httpClient = &http.Client{
Transport: &http.Transport{
DisableKeepAlives: true,
Expand Down
11 changes: 11 additions & 0 deletions cats_suite_helpers/cats_suite_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,17 @@ func CommaDelimitedSecurityGroupsDescribe(description string, callback func()) b
})
}

func IdentityAwareRoutingDescribe(description string, callback func()) bool {
return Describe("[identity aware routing]", func() {
BeforeEach(func() {
if !Config.GetIncludeIdentityAwareRouting() {
Skip(skip_messages.SkipIdentityAwareRoutingMessage)
}
})
Describe(description, callback)
})
}

func ServiceDiscoveryDescribe(description string, callback func()) bool {
return Describe("[service discovery]", func() {
BeforeEach(func() {
Expand Down
1 change: 1 addition & 0 deletions cats_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
_ "github.com/cloudfoundry/cf-acceptance-tests/docker"
_ "github.com/cloudfoundry/cf-acceptance-tests/file_based_service_bindings"
_ "github.com/cloudfoundry/cf-acceptance-tests/http2_routing"
_ "github.com/cloudfoundry/cf-acceptance-tests/identity_aware_routing"
_ "github.com/cloudfoundry/cf-acceptance-tests/internet_dependent"
_ "github.com/cloudfoundry/cf-acceptance-tests/ipv6"
_ "github.com/cloudfoundry/cf-acceptance-tests/isolation_segments"
Expand Down
2 changes: 2 additions & 0 deletions helpers/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type CatsConfig interface {
GetIncludeSecurityGroups() bool
GetIncludeServices() bool
GetIncludeUserProvidedServices() bool
GetIncludeIdentityAwareRouting() bool
GetIdentityAwareDomain() string
GetIncludeServiceDiscovery() bool
GetIncludeServiceCredentialBindingRotation() bool
GetIncludeSsh() bool
Expand Down
93 changes: 63 additions & 30 deletions helpers/config/config_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,36 +74,38 @@ type config struct {
VolumeServiceBindConfig *string `json:"volume_service_bind_config"`
VolumeServiceBrokerName *string `json:"volume_service_broker_name"`

IncludeAppSyslogTCP *bool `json:"include_app_syslog_tcp"`
IncludeApps *bool `json:"include_apps"`
IncludeContainerNetworking *bool `json:"include_container_networking"`
IncludeDeployments *bool `json:"include_deployments"`
IncludeDetect *bool `json:"include_detect"`
IncludeDocker *bool `json:"include_docker"`
IncludeCNB *bool `json:"include_cnb"`
IncludeFileBasedServiceBindings *bool `json:"include_file_based_service_bindings"`
IncludeInternetDependent *bool `json:"include_internet_dependent"`
IncludeIsolationSegments *bool `json:"include_isolation_segments"`
IncludePrivateDockerRegistry *bool `json:"include_private_docker_registry"`
IncludeRouteServices *bool `json:"include_route_services"`
IncludeRouting *bool `json:"include_routing"`
IncludeRoutingIsolationSegments *bool `json:"include_routing_isolation_segments"`
IncludeSSO *bool `json:"include_sso"`
IncludeSecurityGroups *bool `json:"include_security_groups"`
IncludeServiceDiscovery *bool `json:"include_service_discovery"`
IncludeServiceInstanceSharing *bool `json:"include_service_instance_sharing"`
IncludeServiceCredentialBindingRotation *bool `json:"include_service_credential_binding_rotation"`
IncludeServices *bool `json:"include_services"`
IncludeUserProvidedServices *bool `json:"include_user_provided_services"`
IncludeSsh *bool `json:"include_ssh"`
IncludeTCPIsolationSegments *bool `json:"include_tcp_isolation_segments"`
IncludeHTTP2Routing *bool `json:"include_http2_routing"`
IncludeTCPRouting *bool `json:"include_tcp_routing"`
IncludeTasks *bool `json:"include_tasks"`
IncludeV3 *bool `json:"include_v3"`
IncludeVolumeServices *bool `json:"include_volume_services"`
IncludeZipkin *bool `json:"include_zipkin"`
IncludeIPv6 *bool `json:"include_ipv6"`
IncludeAppSyslogTCP *bool `json:"include_app_syslog_tcp"`
IncludeApps *bool `json:"include_apps"`
IncludeContainerNetworking *bool `json:"include_container_networking"`
IncludeDeployments *bool `json:"include_deployments"`
IncludeDetect *bool `json:"include_detect"`
IncludeDocker *bool `json:"include_docker"`
IncludeCNB *bool `json:"include_cnb"`
IncludeFileBasedServiceBindings *bool `json:"include_file_based_service_bindings"`
IncludeIdentityAwareRouting *bool `json:"include_identity_aware_routing"`
IdentityAwareDomain *string `json:"identity_aware_domain"`
IncludeInternetDependent *bool `json:"include_internet_dependent"`
IncludeIsolationSegments *bool `json:"include_isolation_segments"`
IncludePrivateDockerRegistry *bool `json:"include_private_docker_registry"`
IncludeRouteServices *bool `json:"include_route_services"`
IncludeRouting *bool `json:"include_routing"`
IncludeRoutingIsolationSegments *bool `json:"include_routing_isolation_segments"`
IncludeSSO *bool `json:"include_sso"`
IncludeSecurityGroups *bool `json:"include_security_groups"`
IncludeServiceDiscovery *bool `json:"include_service_discovery"`
IncludeServiceInstanceSharing *bool `json:"include_service_instance_sharing"`
IncludeServiceCredentialBindingRotation *bool `json:"include_service_credential_binding_rotation"`
IncludeServices *bool `json:"include_services"`
IncludeUserProvidedServices *bool `json:"include_user_provided_services"`
IncludeSsh *bool `json:"include_ssh"`
IncludeTCPIsolationSegments *bool `json:"include_tcp_isolation_segments"`
IncludeHTTP2Routing *bool `json:"include_http2_routing"`
IncludeTCPRouting *bool `json:"include_tcp_routing"`
IncludeTasks *bool `json:"include_tasks"`
IncludeV3 *bool `json:"include_v3"`
IncludeVolumeServices *bool `json:"include_volume_services"`
IncludeZipkin *bool `json:"include_zipkin"`
IncludeIPv6 *bool `json:"include_ipv6"`

CredhubMode *string `json:"credhub_mode"`
CredhubLocation *string `json:"credhub_location"`
Expand Down Expand Up @@ -200,6 +202,8 @@ func getDefaults() config {
defaults.IncludeRouteServices = ptrToBool(false)
defaults.IncludeSSO = ptrToBool(false)
defaults.IncludeSecurityGroups = ptrToBool(false)
defaults.IncludeIdentityAwareRouting = ptrToBool(false)
defaults.IdentityAwareDomain = ptrToString("apps.identity")
defaults.IncludeServiceDiscovery = ptrToBool(false)
defaults.IncludeServices = ptrToBool(false)
defaults.IncludeUserProvidedServices = ptrToBool(false)
Expand Down Expand Up @@ -356,6 +360,11 @@ func validateConfig(config *config) error {
errs = errors.Join(errs, err)
}

err = validateIdentityAwareRouting(config)
if err != nil {
errs = errors.Join(errs, err)
}

err = validateTimeoutScale(config)
if err != nil {
errs = errors.Join(errs, err)
Expand Down Expand Up @@ -775,6 +784,22 @@ func validateVolumeServices(config *config) error {
return nil
}

func validateIdentityAwareRouting(config *config) error {
if config.IncludeIdentityAwareRouting == nil {
return fmt.Errorf("* 'include_identity_aware_routing' must not be null")
}

if !config.GetIncludeIdentityAwareRouting() {
return nil
}

if config.IdentityAwareDomain == nil {
return fmt.Errorf("* Invalid configuration: 'identity_aware_domain' must not be null if 'include_identity_aware_routing' is true")
}

return nil
}

func validateWindows(config *config) error {
if config.IncludeWindows == nil {
return fmt.Errorf("* 'include_windows' must not be null")
Expand Down Expand Up @@ -1124,6 +1149,14 @@ func (c *config) GetIncludeWindows() bool {
return *c.IncludeWindows
}

func (c *config) GetIncludeIdentityAwareRouting() bool {
return *c.IncludeIdentityAwareRouting
}

func (c *config) GetIdentityAwareDomain() string {
return *c.IdentityAwareDomain
}

func (c *config) GetIncludeServiceDiscovery() bool {
return *c.IncludeServiceDiscovery
}
Expand Down
2 changes: 2 additions & 0 deletions helpers/skip_messages/skip_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const SkipIsolationSegmentsMessage = `Skipping this test because config.IncludeI
const SkipRoutingIsolationSegmentsMessage = `Skipping this test because Config.IncludeRoutingIsolationSegments is set to 'false'.`
const SkipZipkinMessage = `Skipping this test because config.IncludeZipkin is set to 'false'`
const SkipServiceDiscoveryMessage = `Skipping this test because config.IncludeServiceDiscovery is set to 'false'.`
const SkipIdentityAwareRoutingMessage = `Skipping this test because config.IncludeIdentityAwareRouting is set to 'false'.
NOTE: Ensure that identity-aware routing is enabled and the identity-aware domain is configured before running this test.`
const SkipServiceInstanceSharingMessage = `Skipping this test because config.IncludeServiceInstanceSharing is set to 'false'.`
const SkipServiceCredentialBindingRotationMessage = `Skipping this test because config.IncludeServiceCredentialBindingRotation is set to 'false'.`
const SkipCapiExperimentalMessage = `Skipping this test because config.IncludeCapiExperimental is set to 'false'.`
Expand Down
Loading