Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
GetIncludeSsh() bool
GetIncludeTasks() bool
Expand Down
15 changes: 15 additions & 0 deletions helpers/config/config_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ type config struct {
IncludeRoutingIsolationSegments *bool `json:"include_routing_isolation_segments"`
IncludeSSO *bool `json:"include_sso"`
IncludeSecurityGroups *bool `json:"include_security_groups"`
IncludeIdentityAwareRouting *bool `json:"include_identity_aware_routing"`
IdentityAwareDomain *string `json:"identity_aware_domain"`
IncludeServiceDiscovery *bool `json:"include_service_discovery"`
IncludeServiceInstanceSharing *bool `json:"include_service_instance_sharing"`
IncludeServices *bool `json:"include_services"`
Expand Down Expand Up @@ -199,6 +201,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 @@ -479,6 +483,9 @@ func validateConfig(config *config) error {
if config.IncludeSecurityGroups == nil {
errs = errors.Join(errs, fmt.Errorf("* 'include_security_groups' must not be null"))
}
if config.IncludeIdentityAwareRouting == nil {
errs = errors.Join(errs, fmt.Errorf("* 'include_identity_aware_routing' must not be null"))
}
if config.IncludeServiceDiscovery == nil {
errs = errors.Join(errs, fmt.Errorf("* 'include_service_discovery' must not be null"))
}
Expand Down Expand Up @@ -1115,6 +1122,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 SkipCapiExperimentalMessage = `Skipping this test because config.IncludeCapiExperimental is set to 'false'.`
const SkipWindowsTasksMessage = `Skipping Windows tasks tests (requires diego-release v1.20.0 and above)`
Expand Down
Loading