diff --git a/command/v7/login_command_test.go b/command/v7/login_command_test.go index 3785165051f..acf142cd9b1 100644 --- a/command/v7/login_command_test.go +++ b/command/v7/login_command_test.go @@ -309,15 +309,27 @@ var _ = Describe("login Command", func() { }) }) - When("targeting the API fails due to an invalid certificate", func() { - BeforeEach(func() { - cmd.APIEndpoint = "api.example.com" - fakeActor.SetTargetReturns(nil, ccerror.UnverifiedServerError{URL: "https://api.example.com"}) + When("certificate is invalid", func() { + When("targeting the API without setting --skip-ssl-validation flag", func() { + BeforeEach(func() { + cmd.APIEndpoint = "api.example.com" + fakeActor.SetTargetReturns(nil, ccerror.UnverifiedServerError{URL: "https://api.example.com"}) + }) + + It("returns an error mentioning the login command", func() { + Expect(executeErr).To(MatchError( + translatableerror.InvalidSSLCertError{URL: "https://api.example.com", SuggestedCommand: "login"})) + }) }) - It("returns an error mentioning the login command", func() { - Expect(executeErr).To(MatchError( - translatableerror.InvalidSSLCertError{URL: "https://api.example.com", SuggestedCommand: "login"})) + When("targeting the API with --skip-ssl-validation flag", func() { + BeforeEach(func() { + cmd.APIEndpoint = "api.example.com" + }) + + It("login succeeds", func() { + Expect(executeErr).NotTo(HaveOccurred()) + }) }) }) }) diff --git a/integration/shared/isolated/logs_command_test.go b/integration/shared/isolated/logs_command_test.go deleted file mode 100644 index 5929bef7736..00000000000 --- a/integration/shared/isolated/logs_command_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package isolated - -import ( - "encoding/base64" - "fmt" - "net/http" - "runtime" - "strconv" - "time" - - "code.cloudfoundry.org/cli/integration/helpers" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - . "github.com/onsi/gomega/gbytes" - . "github.com/onsi/gomega/gexec" - "github.com/onsi/gomega/ghttp" -) - -var _ = Describe("logs command", func() { - var server *ghttp.Server - - BeforeEach(func() { - server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) - helpers.AddLoginRoutes(server) - - helpers.AddHandler(server, - http.MethodGet, - "/v3/organizations?order_by=name", - http.StatusOK, - []byte( - `{ - "total_results": 1, - "total_pages": 1, - "resources": [ - { - "guid": "f3ea75ba-ea6b-439f-8889-b07abf718e6a", - "name": "some-fake-org" - } - ]}`), - ) - - // The v6 version of this command makes the below request when logging in. - // See below for comparison with v7 version. - helpers.AddHandler(server, - http.MethodGet, - "/v3/spaces?organization_guids=f3ea75ba-ea6b-439f-8889-b07abf718e6a", - http.StatusOK, - []byte( - `{ - "total_results": 1, - "total_pages": 1, - "resources": [ - { - "guid": "1704b4e7-14bb-4b7b-bc23-0b8d23a60238", - "name": "some-fake-space" - } - ]}`), - ) - - // The v7 version of this command makes the below request when logging in, - // which is similar to the v6 version above except for the additional 'order_by' - // query parameter. Rather than split these tests across two files, we just add - // a handler for both routes (with and without 'order_by'). - helpers.AddHandler(server, - http.MethodGet, - "/v3/spaces?order_by=name&organization_guids=f3ea75ba-ea6b-439f-8889-b07abf718e6a", - http.StatusOK, - []byte( - `{ - "total_results": 1, - "total_pages": 1, - "resources": [ - { - "guid": "1704b4e7-14bb-4b7b-bc23-0b8d23a60238", - "name": "some-fake-space" - } - ]}`), - ) - - helpers.AddHandler(server, - http.MethodGet, - "/v2/apps?q=name%3Asome-fake-app&q=space_guid%3A1704b4e7-14bb-4b7b-bc23-0b8d23a60238", - http.StatusOK, - []byte( - `{ - "total_results": 1, - "total_pages": 1, - "resources": [ - { - "metadata": { - "guid": "d5d27772-315f-474b-8673-57e34ce2db2c" - }, - "entity": { - "name": "some-fake-app" - } - } - ]}`), - ) - - helpers.AddHandler(server, - http.MethodGet, - "/v3/apps?names=some-fake-app&space_guids=1704b4e7-14bb-4b7b-bc23-0b8d23a60238", - http.StatusOK, - []byte( - `{ - "total_results": 1, - "total_pages": 1, - "resources": [ - { - "guid": "d5d27772-315f-474b-8673-57e34ce2db2c", - "name": "some-fake-app" - } - ]}`), - ) - - helpers.AddHandler(server, - http.MethodGet, - "/api/v1/info", - http.StatusOK, - []byte(`{"version":"2.6.8"}`), - ) - }) - - AfterEach(func() { - server.Close() - }) - - Describe("streaming logs", func() { - - const logMessage = "hello from log-cache" - var returnEmptyEnvelope bool - - onWindows := runtime.GOOS == "windows" - - BeforeEach(func() { - latestEnvelopeTimestamp := "1581447006352020890" - latestEnvelopeTimestampMinusOneSecond := "1581447005352020890" - nextEnvelopeTimestamp := "1581447009352020890" - nextEnvelopeTimestampPlusOneNanosecond := "1581447009352020891" - - server.RouteToHandler( - http.MethodGet, - "/api/v1/read/d5d27772-315f-474b-8673-57e34ce2db2c", - func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - switch r.URL.RawQuery { - case fmt.Sprintf("descending=true&limit=1&start_time=%s", strconv.FormatInt(time.Time{}.UnixNano(), 10)): - if returnEmptyEnvelope { - _, err := w.Write([]byte(`{}`)) - Expect(err).ToNot(HaveOccurred()) - returnEmptyEnvelope = false // Allow the CLI to continue after receiving an empty envelope - } else { - _, err := w.Write([]byte(fmt.Sprintf(` - { - "envelopes": { - "batch": [ - { - "timestamp": "%s", - "source_id": "d5d27772-315f-474b-8673-57e34ce2db2c" - } - ] - } - }`, latestEnvelopeTimestamp))) - Expect(err).ToNot(HaveOccurred()) - } - case fmt.Sprintf("envelope_types=LOG&start_time=%s", latestEnvelopeTimestampMinusOneSecond): - _, err := w.Write([]byte(fmt.Sprintf(`{ - "envelopes": { - "batch": [ - { - "timestamp": "%s", - "source_id": "d5d27772-315f-474b-8673-57e34ce2db2c", - "tags": { - "__v1_type": "LogMessage" - }, - "log": { - "payload": "%s", - "type": "OUT" - } - } - ] - } - }`, nextEnvelopeTimestamp, base64.StdEncoding.EncodeToString([]byte(logMessage))))) - Expect(err).ToNot(HaveOccurred()) - case fmt.Sprintf("envelope_types=LOG&start_time=%s", nextEnvelopeTimestampPlusOneNanosecond): - _, err := w.Write([]byte("{}")) - Expect(err).ToNot(HaveOccurred()) - default: - Fail(fmt.Sprintf("Unhandled log-cache api query string: %s", r.URL.RawQuery)) - } - }) - }) - - When("there already is an envelope in the log cache", func() { - JustBeforeEach(func() { - returnEmptyEnvelope = false - }) - - It("fetches logs with a timestamp just prior to the latest log envelope", func() { - username, password := helpers.GetCredentials() - session := helpers.CF("login", "-a", server.URL(), "-u", username, "-p", password, "--skip-ssl-validation") - Eventually(session).Should(Exit(0)) - - session = helpers.CF("logs", "some-fake-app") - Eventually(session).Should(Say(logMessage)) - if onWindows { - session.Kill() - Eventually(session).Should(Exit()) - } else { - session.Interrupt() - Eventually(session).Should(Exit(0), "Interrupt should be handled and fail gracefully") - } - }) - }) - - When("there is not yet an envelope in the log cache", func() { - JustBeforeEach(func() { - returnEmptyEnvelope = true - }) - - // TODO: the case where log-cache has no envelopes yet may be "special": we may want to switch to "start from your oldest envelope" approach. - It("retries until there is an initial envelope, and then fetches logs with a timestamp just prior to the latest log envelope", func() { - username, password := helpers.GetCredentials() - session := helpers.CF("login", "-a", server.URL(), "-u", username, "-p", password, "--skip-ssl-validation") - Eventually(session).Should(Exit(0)) - - session = helpers.CF("logs", "some-fake-app") - Eventually(session).Should(Say(logMessage)) - if onWindows { - session.Kill() - Eventually(session).Should(Exit()) - } else { - session.Interrupt() - Eventually(session).Should(Exit(0)) - } - }) - }) - }) -}) diff --git a/integration/v7/isolated/api_command_test.go b/integration/v7/isolated/api_command_test.go index 8496aa903d5..99dfcd972b3 100644 --- a/integration/v7/isolated/api_command_test.go +++ b/integration/v7/isolated/api_command_test.go @@ -2,11 +2,9 @@ package isolated import ( "encoding/json" - "net/http" "os" "os/exec" "path/filepath" - "strings" "code.cloudfoundry.org/cli/integration/helpers" "code.cloudfoundry.org/cli/util/configv3" @@ -14,7 +12,6 @@ import ( . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" . "github.com/onsi/gomega/gexec" - "github.com/onsi/gomega/ghttp" ) var _ = Describe("api command", func() { @@ -133,25 +130,17 @@ var _ = Describe("api command", func() { When("Skip SSL Validation is required", func() { Context("API has SSL", func() { - var server *ghttp.Server - - BeforeEach(func() { + It("warns about skip SSL", func() { cliVersion := "1.0.0" - server = helpers.StartMockServerWithMinimumCLIVersion(cliVersion) + server := helpers.StartMockServerWithMinimumCLIVersion(cliVersion) apiURL = server.URL() - }) - - AfterEach(func() { - server.Close() - }) - - It("warns about skip SSL", func() { session := helpers.CF("api", apiURL) Eventually(session).Should(Say("Setting API endpoint to %s...", apiURL)) Eventually(session.Err).Should(Say("x509: certificate has expired or is not yet valid|SSL Certificate Error x509: certificate is valid for|Invalid SSL Cert for %s", apiURL)) Eventually(session.Err).Should(Say("TIP: Use 'cf api --skip-ssl-validation' to continue with an insecure API endpoint")) Eventually(session).Should(Say("FAILED")) Eventually(session).Should(Exit(1)) + defer server.Close() }) It("sets the API endpoint", func() { @@ -164,78 +153,6 @@ var _ = Describe("api command", func() { }) }) - Context("API does not have SSL", func() { - var server *ghttp.Server - - BeforeEach(func() { - server = ghttp.NewServer() - serverAPIURL := server.URL()[7:] - - response := `{ - "links":{ - "self":{ - "href":"http://APISERVER" - }, - "bits_service":null, - "cloud_controller_v2":{ - "href":"http://APISERVER/v2", - "meta":{ - "version":"2.146.0" - } - }, - "cloud_controller_v3":{ - "href":"http://APISERVER/v3", - "meta":{ - "version":"3.81.0" - } - } - } -}` - response = strings.Replace(response, "APISERVER", serverAPIURL, -1) - server.AppendHandlers( - ghttp.CombineHandlers( - ghttp.VerifyRequest("GET", "/"), - ghttp.RespondWith(http.StatusOK, response), - ), - ) - - response2 := `{ - "links":{ - "self":{ - "href":"http://APISERVER/v3" - } - } -}` - response2 = strings.Replace(response2, "APISERVER", serverAPIURL, -1) - server.AppendHandlers( - ghttp.CombineHandlers( - ghttp.VerifyRequest("GET", "/v3"), - ghttp.RespondWith(http.StatusOK, response2), - ), - ) - - server.AppendHandlers( - ghttp.CombineHandlers( - ghttp.VerifyRequest("GET", "/"), - ghttp.RespondWith(http.StatusOK, response), - ), - ) - }) - - AfterEach(func() { - server.Close() - }) - - It("falls back to http and gives a warning", func() { - session := helpers.CF("api", server.URL(), "--skip-ssl-validation") - Eventually(session).Should(Say("Setting API endpoint to %s...", server.URL())) - Eventually(session).Should(Say("Warning: Insecure http API endpoint detected: secure https API endpoints are recommended")) - Eventually(session).Should(Say("OK")) - Eventually(session).Should(Say("Not logged in. Use 'cf login' or 'cf login --sso' to log in.")) - Eventually(session).Should(Exit(0)) - }) - }) - It("sets SSL Disabled in the config file to true", func() { command := exec.Command("cf", "api", apiURL, "--skip-ssl-validation") session, err := Start(command, GinkgoWriter, GinkgoWriter) diff --git a/integration/v7/isolated/login_command_test.go b/integration/v7/isolated/login_command_test.go index 34081b40051..94680e3348c 100644 --- a/integration/v7/isolated/login_command_test.go +++ b/integration/v7/isolated/login_command_test.go @@ -3,7 +3,6 @@ package isolated import ( "encoding/json" "fmt" - "net/http" "net/url" "os" "path/filepath" @@ -15,7 +14,6 @@ import ( . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" . "github.com/onsi/gomega/gexec" - "github.com/onsi/gomega/ghttp" ) var _ = Describe("login command", func() { @@ -243,63 +241,6 @@ var _ = Describe("login command", func() { Expect(session).Should(Say("API endpoint: %s", apiURL)) }) }) - - When("the SSL Certificate is invalid", func() { - var server *ghttp.Server - - BeforeEach(func() { - cliVersion := "1.0.0" - server = helpers.StartMockServerWithMinimumCLIVersion(cliVersion) - fakeTokenResponse := map[string]string{ - "access_token": "", - "token_type": "bearer", - } - server.RouteToHandler(http.MethodPost, "/oauth/token", - ghttp.RespondWithJSONEncoded(http.StatusOK, fakeTokenResponse)) - server.RouteToHandler(http.MethodGet, "/v3/organizations", - ghttp.RespondWith(http.StatusOK, `{ - "total_results": 0, - "total_pages": 1, - "resources": []}`)) - }) - - AfterEach(func() { - server.Close() - }) - - It("errors when --skip-ssl-validation is not provided", func() { - session := helpers.CF("login", "-a", server.URL()) - Eventually(session).Should(Say("API endpoint: %s", server.URL())) - Eventually(session).Should(Say("FAILED")) - Eventually(session.Err).Should(Say("Invalid SSL Cert for %s", server.URL())) - Eventually(session.Err).Should(Say("TIP: Use 'cf login --skip-ssl-validation' to continue with an insecure API endpoint")) - Eventually(session).Should(Exit(1)) - }) - - It("doesn't complain about an invalid cert when we specify --skip-ssl-validation", func() { - session := helpers.CF("login", "-a", server.URL(), "--skip-ssl-validation") - Eventually(session).Should(Exit(0)) - - Expect(string(session.Err.Contents())).Should(Not(ContainSubstring("Invalid SSL Cert for %s", server.URL()))) - }) - - When("targeted with --skip-ssl-validation", func() { - BeforeEach(func() { - Eventually(helpers.CF("api", server.URL(), "--skip-ssl-validation")).Should(Exit(0)) - }) - - When("logging in without --skip-ssl-validation", func() { - It("displays a helpful error message and exits 1", func() { - session := helpers.CF("login", "-a", server.URL()) - Eventually(session).Should(Say("API endpoint: %s", server.URL())) - Eventually(session).Should(Say("FAILED")) - Eventually(session.Err).Should(Say("Invalid SSL Cert for %s", server.URL())) - Eventually(session.Err).Should(Say("TIP: Use 'cf login --skip-ssl-validation' to continue with an insecure API endpoint")) - Eventually(session).Should(Exit(1)) - }) - }) - }) - }) }) }) @@ -513,72 +454,6 @@ var _ = Describe("login command", func() { }) }) }) - - When("MFA is enabled", func() { - var ( - mfaCode string - server *ghttp.Server - ) - - BeforeEach(func() { - password = "some-password" - mfaCode = "123456" - server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) - helpers.AddMfa(server, password, mfaCode) - }) - - AfterEach(func() { - server.Close() - }) - - When("correct MFA code and credentials are provided", func() { - BeforeEach(func() { - fakeTokenResponse := map[string]string{ - "access_token": "", - "token_type": "bearer", - } - server.RouteToHandler(http.MethodPost, "/oauth/token", - ghttp.RespondWithJSONEncoded(http.StatusOK, fakeTokenResponse)) - server.RouteToHandler(http.MethodGet, "/v3/organizations", - ghttp.RespondWith(http.StatusOK, `{ - "total_results": 0, - "total_pages": 1, - "resources": []}`)) - }) - - It("logs in the user", func() { - input := NewBuffer() - _, err := input.Write([]byte(username + "\n" + password + "\n" + mfaCode + "\n")) - Expect(err).ToNot(HaveOccurred()) - session := helpers.CFWithStdin(input, "login") - Eventually(session).Should(Say("Email: ")) - Eventually(session).Should(Say("\n")) - Eventually(session).Should(Say("Password:")) - Eventually(session).Should(Say("\n")) - Eventually(session).Should(Say("MFA Code \\( Register at %[1]s \\)", server.URL())) - Eventually(session).Should(Exit(0)) - }) - }) - - When("incorrect MFA code and credentials are provided", func() { - It("fails", func() { - input := NewBuffer() - wrongMfaCode := mfaCode + "foo" - _, err := input.Write([]byte(username + "\n" + password + "\n" + wrongMfaCode + "\n" + password + "\n" + wrongMfaCode + "\n")) - Expect(err).ToNot(HaveOccurred()) - session := helpers.CFWithStdin(input, "login") - Eventually(session).Should(Say("Password: ")) - Eventually(session).Should(Say("MFA Code \\( Register at %[1]s \\)", server.URL())) - Eventually(session).Should(Say("Password: ")) - Eventually(session).Should(Say("MFA Code \\( Register at %[1]s \\)", server.URL())) - Eventually(session).Should(Say("Not logged in. Use 'cf login' or 'cf login --sso' to log in.")) - Eventually(session).Should(Say("FAILED")) - Eventually(session.Err).Should(Say("Unable to authenticate.")) - - Eventually(session).Should(Exit(1)) - }) - }) - }) }) Describe("Client Credentials", func() { @@ -667,38 +542,6 @@ var _ = Describe("login command", func() { Eventually(setOrgRoleSession).Should(Exit(0)) }) - When("there are more than 50 orgs", func() { - var server *ghttp.Server - - BeforeEach(func() { - server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) - helpers.AddLoginRoutes(server) - helpers.AddFiftyOneOrgs(server) - // handle request for spaces under "org20" - helpers.AddEmptyPaginatedResponse(server, "/v3/spaces?order_by=name&organization_guids=f6653aac-938e-4469-9a66-56a02796412b") - }) - - AfterEach(func() { - server.Close() - }) - - It("displays a message and prompts the user for the org name", func() { - input := NewBuffer() - _, wErr := input.Write([]byte(fmt.Sprintf("%s\n", "org20"))) // "org20" is one of the orgs in the test fixture - Expect(wErr).ToNot(HaveOccurred()) - - session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "--skip-ssl-validation") - - Eventually(session).Should(Say("Select an org:")) - Eventually(session).Should(Say("There are too many options to display; please type in the name.")) - Eventually(session).Should(Say("\n\n")) - Eventually(session).Should(Say(regexp.QuoteMeta(`Org (enter to skip):`))) - Eventually(session).Should(Say(`Targeted org org20\.`)) - - Eventually(session).Should(Exit(0)) - }) - }) - When("user selects an organization by using numbered list", func() { It("prompts the user for org and targets the selected org", func() { input := NewBuffer() @@ -1113,35 +956,6 @@ var _ = Describe("login command", func() { Eventually(targetSession).Should(Say("No space targeted, use 'cf target -s SPACE'")) }) }) - - When("there are more than 50 spaces", func() { - var server *ghttp.Server - BeforeEach(func() { - server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) - helpers.AddLoginRoutes(server) - helpers.AddFiftyOneSpaces(server) - }) - - AfterEach(func() { - server.Close() - }) - - It("displays a message and prompts the user for the space name", func() { - input := NewBuffer() - _, wErr := input.Write([]byte(fmt.Sprintf("%s\n", "test-space-1"))) - Expect(wErr).ToNot(HaveOccurred()) - - session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "--skip-ssl-validation") - - Eventually(session).Should(Say("Select a space:")) - Eventually(session).Should(Say("There are too many options to display; please type in the name.")) - Eventually(session).Should(Say("\n\n")) - Eventually(session).Should(Say(regexp.QuoteMeta(`Space (enter to skip):`))) - Eventually(session).Should(Say(`Targeted space test-space-1\.`)) - - Eventually(session).Should(Exit(0)) - }) - }) }) }) })