Skip to content

Commit

Permalink
feat(eventgenerator): Integrate cf api with event generator (#3357)
Browse files Browse the repository at this point in the history
* Adds cf_Server config for scalingengine

* Adds xfcc cf endpoint support to scaling engine

* Remove debug println

* Update jobs/scalingengine/spec

Co-authored-by: Silvestre Zabala <[email protected]>

* Update jobs/scalingengine/spec

Co-authored-by: Silvestre Zabala <[email protected]>

* Remove pending test

* Removes subrouter in api server

* WIP

* Fix issue with routes

* Remove EventgeneratorServer interface from server.go

* Adds xfcc cf endpoint support to scaling engine

* WIP

* Wip2

* Refactor routes

* Refactor X-Forwarded-Client-Cert header handling and update tests

 • Remove direct sha256 usage in PublicApiHandler and replace with new auth.Cert abstraction.
 • Add auth.NewCert and auth.Cert.GetXFCCHeader to manage certificate encoding and header creation.
 • Update PublicApiHandler and tests to use the new auth.Cert methods for setting the X-Forwarded-Client-Cert header.
 • Adjust testhelpers.GenerateClientCert and testhelpers.SetXFCCCertHeader to align with new certificate handling logic.

* Fix test

* wip fix test

* Enable generate-fakes target for integration tests in Makefile

* Fix wrong merge conflict on public api handler

* Fix regular expression to parse organization unit

* Fix lint

* Fix integration tests

* Remove logging

* Remove unused reflect import and delete redundant nil check in DetachScalingPolicy function.

* Add GinkgoHelper call to ApiRunner's Start method in api_suite_test.

* Refactor CF instance certificate handling to support TLS

 - handle CF_INSTANCE_CERT and CF_INSTANCE_KEY
 - Remove `CfInstanceCert` from `Config` struct and related code
 - Generate RSA keys and certificates for testing in `api_test.go` and `config_test.go`
 - Set environment variables for instance keys and certs in tests
 - Update `config#configureEventGenerator` to use environment variables for TLS config
 - Remove unused `auth` import and related code in `public_api_handler.go`
 - Create `MaterializeContentInFile` function in `configutil` for file operations
 - Add `GenerateClientCertWithPrivateKey` and `GenerateClientKeyWithPrivateKey` in `testhelpers`

* Fix lints

* Remove redundant comments about policy and schedule synchronization in PublicApiHandler

* Remove unused certificate pool setup code from config.go in autoscaler/api

* Remove CF_INSTANCE_CERT handling from VCAPConfiguration

 • Eliminate GetCfInstanceCert method and associated environment variable usage.
 • Update tests to reflect removal of CF_INSTANCE_CERT handling.

* Remove redundant code and TODO comment in resetDefaultPolicy function

* Remove auth helpers from golang API server package spec

* Reads CF_INSTANCE_CERT and KEY from filepath

 - Make `generate-fakes` target `.PHONY` in Makefile
 - Remove dependency of `generate-fakes` from `testsuite` target
 - Simplify `configureEventGenerator` function by directly setting `CertFile` and `KeyFile` from environment variables
 - Update tests to reflect changes in `configureEventGenerator` and remove unnecessary file creation for `CF_INSTANCE_CERT` and `CF_INSTANCE_KEY`

* Adds initial implementation of TLSReloadTransport

* Reduce load of parsing the certificate on every request to check cert expiration date

* Refactor

* Refactor TLSReloadTransport to use non-pointer time.Time for cert expiration

 • Changed certExpiration from a pointer to a non-pointer time.Time type.
 • Updated GetCertExpiration and certificateExpiringWithin methods to handle the non-pointer type.
 • Removed unnecessary pointer dereferences in httpclient_test.go.

* Simplify test

* 🤖🦾🛠️ go mod tidy & make package-specs

* Fix broken tests when tls config not defined in httpclinet

* Fix api/cmd test to support CF_INSTANCE_CERT

* fix linters

---------

Co-authored-by: Silvestre Zabala <[email protected]>
  • Loading branch information
bonzofenix and silvestre authored Dec 27, 2024
1 parent 27b5ce2 commit 98ed150
Show file tree
Hide file tree
Showing 34 changed files with 1,306 additions and 941 deletions.
3 changes: 2 additions & 1 deletion src/autoscaler/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,12 @@ build_test-%: generate-fakes

check: fmt lint build test

.PHONY: generate-fakes
test: generate-fakes
@echo "Running tests"
APP_AUTOSCALER_TEST_RUN='true' go run 'github.com/onsi/ginkgo/v2/ginkgo@${GINKGO_VERSION}' -p ${GINKGO_OPTS} ${TEST} --skip-package='integration'

testsuite: generate-fakes
testsuite:
@echo " - using DBURL=${DBURL} TEST=${TEST}"
APP_AUTOSCALER_TEST_RUN='true' go run 'github.com/onsi/ginkgo/v2/ginkgo@${GINKGO_VERSION}' -p ${GINKGO_OPTS} ${TEST}

Expand Down
1 change: 1 addition & 0 deletions src/autoscaler/api/cmd/api/api_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ func NewApiRunner() *ApiRunner {
}

func (ap *ApiRunner) Start() {
GinkgoHelper()
// #nosec G204
apSession, err := gexec.Start(exec.Command(
apPath,
Expand Down
40 changes: 35 additions & 5 deletions src/autoscaler/api/cmd/api/api_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main_test

import (
"crypto/rand"
"crypto/rsa"
"fmt"
"io"
"net/http"
Expand All @@ -9,9 +11,9 @@ import (
"strings"

"code.cloudfoundry.org/app-autoscaler/src/autoscaler/api/config"
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/configutil"
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/db"

. "code.cloudfoundry.org/app-autoscaler/src/autoscaler/testhelpers"
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/testhelpers"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -44,9 +46,9 @@ var _ = Describe("Api", func() {

vcapPort = 8080 + GinkgoParallelProcess()

brokerHttpClient = NewServiceBrokerClient()
brokerHttpClient = testhelpers.NewServiceBrokerClient()
healthHttpClient = &http.Client{}
apiHttpClient = NewPublicApiClient()
apiHttpClient = testhelpers.NewPublicApiClient()
cfServerHttpClient = &http.Client{}

serverURL, err = url.Parse(fmt.Sprintf("https://127.0.0.1:%d", cfg.Server.Port))
Expand Down Expand Up @@ -166,7 +168,7 @@ var _ = Describe("Api", func() {

bodyBytes, err := io.ReadAll(rsp.Body)

FailOnError("Read failed", err)
testhelpers.FailOnError("Read failed", err)
if len(bodyBytes) == 0 {
Fail("body empty")
}
Expand Down Expand Up @@ -297,7 +299,29 @@ var _ = Describe("Api", func() {
})

When("running CF server", func() {
var (
cfInstanceKeyFile string
cfInstanceCertFile string
)

BeforeEach(func() {
rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
Expect(err).NotTo(HaveOccurred())

cfInstanceCert, err := testhelpers.GenerateClientCertWithPrivateKey("org-guid", "space-guid", rsaPrivateKey)
Expect(err).NotTo(HaveOccurred())

certTmpDir := os.TempDir()

cfInstanceCertFile, err := configutil.MaterializeContentInFile(certTmpDir, "eventgenerator.crt", string(cfInstanceCert))
Expect(err).NotTo(HaveOccurred())
os.Setenv("CF_INSTANCE_CERT", string(cfInstanceCertFile))

cfInstanceKey := testhelpers.GenerateClientKeyWithPrivateKey(rsaPrivateKey)
cfInstanceKeyFile, err = configutil.MaterializeContentInFile(certTmpDir, "eventgenerator.key", string(cfInstanceKey))
Expect(err).NotTo(HaveOccurred())
os.Setenv("CF_INSTANCE_KEY", string(cfInstanceKeyFile))

os.Setenv("VCAP_APPLICATION", "{}")
os.Setenv("VCAP_SERVICES", getVcapServices())
os.Setenv("PORT", fmt.Sprintf("%d", vcapPort))
Expand All @@ -306,6 +330,12 @@ var _ = Describe("Api", func() {
AfterEach(func() {
runner.Interrupt()
Eventually(runner.Session, 5).Should(Exit(0))

os.Remove(cfInstanceKeyFile)
os.Remove(cfInstanceCertFile)

os.Unsetenv("CF_INSTANCE_KEY")
os.Unsetenv("CF_INSTANCE_CERT")
os.Unsetenv("VCAP_APPLICATION")
os.Unsetenv("VCAP_SERVICES")
os.Unsetenv("PORT")
Expand Down
8 changes: 8 additions & 0 deletions src/autoscaler/api/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,17 @@ func loadVcapConfig(conf *Config, vcapReader configutil.VCAPConfigurationReader)
if err := configureBindingDb(conf, vcapReader); err != nil {
return err
}

configureEventGenerator(conf)

return nil
}

func configureEventGenerator(conf *Config) {
conf.EventGenerator.TLSClientCerts.CertFile = os.Getenv("CF_INSTANCE_CERT")
conf.EventGenerator.TLSClientCerts.KeyFile = os.Getenv("CF_INSTANCE_KEY")
}

func configurePolicyDb(conf *Config, vcapReader configutil.VCAPConfigurationReader) error {
currentPolicyDb, ok := conf.Db[db.PolicyDb]
if !ok {
Expand Down
20 changes: 20 additions & 0 deletions src/autoscaler/api/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config_test

import (
"fmt"
"os"
"time"

"code.cloudfoundry.org/app-autoscaler/src/autoscaler/fakes"
Expand Down Expand Up @@ -41,6 +42,25 @@ var _ = Describe("Config", func() {
conf, err = LoadConfig("", mockVCAPConfigurationReader)
})

When("vcap CF_INSTANCE_CERT is set", func() {
BeforeEach(func() {
os.Setenv("CF_INSTANCE_KEY", "some/path/in/container/eventgenerator.key")
os.Setenv("CF_INSTANCE_CERT", "some/path/in/container/eventgenerator.crt")
})

AfterEach(func() {
os.Unsetenv("CF_INSTANCE_KEY")
os.Unsetenv("CF_INSTANCE_CERT")

})

It("sets EventGenerator TlSClientCert", func() {
Expect(conf.EventGenerator.TLSClientCerts.KeyFile).To(Equal("some/path/in/container/eventgenerator.key"))
Expect(conf.EventGenerator.TLSClientCerts.CertFile).To(Equal("some/path/in/container/eventgenerator.crt"))

})
})

When("vcap PORT is set to a number", func() {
BeforeEach(func() {
mockVCAPConfigurationReader.GetPortReturns(3333)
Expand Down
2 changes: 1 addition & 1 deletion src/autoscaler/api/publicapiserver/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (mw *Middleware) Oauth(next http.Handler) http.Handler {
if err != nil {
mw.logger.Error("failed to check if user is admin", err, nil)
handlers.WriteJSONResponse(w, http.StatusInternalServerError, models.ErrorResponse{
Code: "Internal-Server-Error",
Code: http.StatusText(http.StatusInternalServerError),
Message: "Failed to check if user is admin"})
return
}
Expand Down
2 changes: 1 addition & 1 deletion src/autoscaler/api/publicapiserver/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ var _ = Describe("Middleware", func() {
})
It("should fail with 500", func() {
CheckResponse(resp, http.StatusInternalServerError, models.ErrorResponse{
Code: "Internal-Server-Error",
Code: http.StatusText(http.StatusInternalServerError),
Message: "Failed to check if user is admin",
})
})
Expand Down
Loading

0 comments on commit 98ed150

Please sign in to comment.