github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/integration/isolated/api_command_test.go (about) 1 package isolated 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 12 "code.cloudfoundry.org/cli/integration/helpers" 13 "code.cloudfoundry.org/cli/util/configv3" 14 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 . "github.com/onsi/gomega/gbytes" 18 . "github.com/onsi/gomega/gexec" 19 "github.com/onsi/gomega/ghttp" 20 ) 21 22 var _ = Describe("api command", func() { 23 Context("no arguments", func() { 24 Context("when the api is set", func() { 25 Context("when the user is not logged in", func() { 26 It("outputs the current api", func() { 27 session := helpers.CF("api") 28 29 Eventually(session.Out).Should(Say("API endpoint:\\s+%s", apiURL)) 30 Eventually(session.Out).Should(Say("API version:\\s+\\d+\\.\\d+\\.\\d+")) 31 Eventually(session).Should(Exit(0)) 32 }) 33 }) 34 35 Context("when the user is logged in", func() { 36 var target, apiVersion, user, org, space string 37 38 BeforeEach(func() { 39 target = "https://api.fake.com" 40 apiVersion = "2.59.0" 41 user = "admin" 42 org = "the-org" 43 space = "the-space" 44 45 userConfig := configv3.Config{ 46 ConfigFile: configv3.CFConfig{ 47 Target: target, 48 APIVersion: apiVersion, 49 AccessToken: "bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImxlZ2FjeS10b2tlbi1rZXkiLCJ0eXAiOiJKV1QifQ.eyJqdGkiOiI3YzZkMDA2MjA2OTI0NmViYWI0ZjBmZjY3NGQ3Zjk4OSIsInN1YiI6Ijk1MTliZTNlLTQ0ZDktNDBkMC1hYjlhLWY0YWNlMTFkZjE1OSIsInNjb3BlIjpbIm9wZW5pZCIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy53cml0ZSIsInNjaW0ucmVhZCIsImNsb3VkX2NvbnRyb2xsZXIuYWRtaW4iLCJ1YWEudXNlciIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy5yZWFkIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJjbG91ZF9jb250cm9sbGVyLndyaXRlIiwiZG9wcGxlci5maXJlaG9zZSIsInNjaW0ud3JpdGUiXSwiY2xpZW50X2lkIjoiY2YiLCJjaWQiOiJjZiIsImF6cCI6ImNmIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9pZCI6Ijk1MTliZTNlLTQ0ZDktNDBkMC1hYjlhLWY0YWNlMTFkZjE1OSIsIm9yaWdpbiI6InVhYSIsInVzZXJfbmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbiIsImF1dGhfdGltZSI6MTQ3MzI4NDU3NywicmV2X3NpZyI6IjZiMjdkYTZjIiwiaWF0IjoxNDczMjg0NTc3LCJleHAiOjE0NzMyODUxNzcsImlzcyI6Imh0dHBzOi8vdWFhLmJvc2gtbGl0ZS5jb20vb2F1dGgvdG9rZW4iLCJ6aWQiOiJ1YWEiLCJhdWQiOlsiY2YiLCJvcGVuaWQiLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMiLCJzY2ltIiwiY2xvdWRfY29udHJvbGxlciIsInVhYSIsInBhc3N3b3JkIiwiZG9wcGxlciJdfQ.OcH_w9yIKJkEcTZMThIs-qJAHk3G0JwNjG-aomVH9hKye4ciFO6IMQMLKmCBrrAQVc7ST1SZZwq7gv12Dq__6Jp-hai0a2_ADJK-Vc9YXyNZKgYTWIeVNGM1JGdHgFSrBR2Lz7IIrH9HqeN8plrKV5HzU8uI9LL4lyOCjbXJ9cM", 50 TargetedOrganization: configv3.Organization{ 51 Name: org, 52 }, 53 TargetedSpace: configv3.Space{ 54 Name: space, 55 }, 56 }, 57 } 58 err := configv3.WriteConfig(&userConfig) 59 Expect(err).ToNot(HaveOccurred()) 60 }) 61 62 It("outputs the user's target information", func() { 63 command := exec.Command("cf", "api") 64 session, err := Start(command, GinkgoWriter, GinkgoWriter) 65 Expect(err).NotTo(HaveOccurred()) 66 67 Eventually(session.Out).Should(Say("API endpoint:\\s+%s", target)) 68 Eventually(session.Out).Should(Say("API version:\\s+%s", apiVersion)) 69 Eventually(session).Should(Exit(0)) 70 }) 71 }) 72 }) 73 74 Context("when the api is not set", func() { 75 BeforeEach(func() { 76 os.RemoveAll(filepath.Join(homeDir, ".cf")) 77 }) 78 79 It("outputs that nothing is set", func() { 80 command := exec.Command("cf", "api") 81 session, err := Start(command, GinkgoWriter, GinkgoWriter) 82 Expect(err).NotTo(HaveOccurred()) 83 84 Eventually(session.Out).Should(Say("No api endpoint set. Use 'cf api' to set an endpoint")) 85 Eventually(session).Should(Exit(0)) 86 }) 87 }) 88 89 Context("--unset is passed", func() { 90 BeforeEach(func() { 91 92 userConfig := configv3.Config{ 93 ConfigFile: configv3.CFConfig{ 94 ConfigVersion: 3, 95 Target: "https://api.fake.com", 96 APIVersion: "2.59.0", 97 AccessToken: "bearer tokenstuff", 98 TargetedOrganization: configv3.Organization{ 99 Name: "the-org", 100 }, 101 TargetedSpace: configv3.Space{ 102 Name: "the-space", 103 }, 104 }, 105 } 106 err := configv3.WriteConfig(&userConfig) 107 Expect(err).ToNot(HaveOccurred()) 108 }) 109 110 It("clears the targetted context", func() { 111 command := exec.Command("cf", "api", "--unset") 112 session, err := Start(command, GinkgoWriter, GinkgoWriter) 113 Expect(err).NotTo(HaveOccurred()) 114 115 Eventually(session.Out).Should(Say("Unsetting api endpoint...")) 116 Eventually(session.Out).Should(Say("OK")) 117 Eventually(session).Should(Exit(0)) 118 119 rawConfig, err := ioutil.ReadFile(filepath.Join(homeDir, ".cf", "config.json")) 120 Expect(err).NotTo(HaveOccurred()) 121 122 var configFile configv3.CFConfig 123 err = json.Unmarshal(rawConfig, &configFile) 124 Expect(err).NotTo(HaveOccurred()) 125 126 Expect(configFile.ConfigVersion).To(Equal(3)) 127 Expect(configFile.Target).To(BeEmpty()) 128 Expect(configFile.APIVersion).To(BeEmpty()) 129 Expect(configFile.AuthorizationEndpoint).To(BeEmpty()) 130 Expect(configFile.DopplerEndpoint).To(BeEmpty()) 131 Expect(configFile.UAAEndpoint).To(BeEmpty()) 132 Expect(configFile.AccessToken).To(BeEmpty()) 133 Expect(configFile.RefreshToken).To(BeEmpty()) 134 Expect(configFile.TargetedOrganization.GUID).To(BeEmpty()) 135 Expect(configFile.TargetedOrganization.Name).To(BeEmpty()) 136 Expect(configFile.TargetedSpace.GUID).To(BeEmpty()) 137 Expect(configFile.TargetedSpace.Name).To(BeEmpty()) 138 Expect(configFile.TargetedSpace.AllowSSH).To(BeFalse()) 139 Expect(configFile.SkipSSLValidation).To(BeFalse()) 140 }) 141 }) 142 }) 143 144 Context("when Skip SSL Validation is required", func() { 145 Context("api has SSL", func() { 146 BeforeEach(func() { 147 if skipSSLValidation == "" { 148 Skip("SKIP_SSL_VALIDATION is not enabled") 149 } 150 }) 151 152 It("warns about skip SSL", func() { 153 command := exec.Command("cf", "api", apiURL) 154 session, err := Start(command, GinkgoWriter, GinkgoWriter) 155 Expect(err).NotTo(HaveOccurred()) 156 157 Eventually(session.Out).Should(Say("Setting api endpoint to %s...", apiURL)) 158 Eventually(session.Err).Should(Say("SSL Certificate Error x509: certificate is valid for|Invalid SSL Cert for %s", apiURL)) 159 Eventually(session.Err).Should(Say("TIP: Use 'cf api --skip-ssl-validation' to continue with an insecure API endpoint")) 160 Eventually(session.Out).Should(Say("FAILED")) 161 Eventually(session).Should(Exit(1)) 162 }) 163 164 It("sets the API endpoint", func() { 165 command := exec.Command("cf", "api", apiURL, "--skip-ssl-validation") 166 session, err := Start(command, GinkgoWriter, GinkgoWriter) 167 Expect(err).NotTo(HaveOccurred()) 168 169 Eventually(session.Out).Should(Say("Setting api endpoint to %s...", apiURL)) 170 Eventually(session.Out).Should(Say("OK")) 171 Eventually(session.Out).Should(Say("API endpoint:\\s+%s", apiURL)) 172 Eventually(session.Out).Should(Say("API version:\\s+\\d+\\.\\d+\\.\\d+")) 173 Eventually(session).Should(Exit(0)) 174 }) 175 }) 176 177 Context("api does not have SSL", func() { 178 var server *ghttp.Server 179 180 BeforeEach(func() { 181 server = ghttp.NewServer() 182 serverAPIURL := server.URL()[7:] 183 184 response := `{ 185 "name":"", 186 "build":"", 187 "support":"http://support.cloudfoundry.com", 188 "version":0, 189 "description":"", 190 "authorization_endpoint":"https://login.APISERVER", 191 "token_endpoint":"https://uaa.APISERVER", 192 "min_cli_version":null, 193 "min_recommended_cli_version":null, 194 "api_version":"2.59.0", 195 "app_ssh_endpoint":"ssh.APISERVER", 196 "app_ssh_host_key_fingerprint":"a6:d1:08:0b:b0:cb:9b:5f:c4:ba:44:2a:97:26:19:8a", 197 "app_ssh_oauth_client":"ssh-proxy", 198 "logging_endpoint":"wss://loggregator.APISERVER", 199 "doppler_logging_endpoint":"wss://doppler.APISERVER" 200 }` 201 response = strings.Replace(response, "APISERVER", serverAPIURL, -1) 202 server.AppendHandlers( 203 ghttp.CombineHandlers( 204 ghttp.VerifyRequest("GET", "/v2/info"), 205 ghttp.RespondWith(http.StatusOK, response), 206 ), 207 ) 208 }) 209 210 AfterEach(func() { 211 server.Close() 212 }) 213 214 It("falls back to http and gives a warning", func() { 215 command := exec.Command("cf", "api", server.URL(), "--skip-ssl-validation") 216 session, err := Start(command, GinkgoWriter, GinkgoWriter) 217 Expect(err).NotTo(HaveOccurred()) 218 219 Eventually(session.Out).Should(Say("Setting api endpoint to %s...", server.URL())) 220 Eventually(session.Out).Should(Say("Warning: Insecure http API endpoint detected: secure https API endpoints are recommended")) 221 Eventually(session.Out).Should(Say("OK")) 222 Eventually(session.Out).Should(Say("Not logged in. Use 'cf login' to log in.")) 223 Eventually(session).Should(Exit(0)) 224 }) 225 }) 226 227 It("sets SSL Disabled in the config file to true", func() { 228 command := exec.Command("cf", "api", apiURL, "--skip-ssl-validation") 229 session, err := Start(command, GinkgoWriter, GinkgoWriter) 230 Expect(err).NotTo(HaveOccurred()) 231 Eventually(session).Should(Exit(0)) 232 233 rawConfig, err := ioutil.ReadFile(filepath.Join(homeDir, ".cf", "config.json")) 234 Expect(err).NotTo(HaveOccurred()) 235 236 var configFile configv3.CFConfig 237 err = json.Unmarshal(rawConfig, &configFile) 238 Expect(err).NotTo(HaveOccurred()) 239 240 Expect(configFile.SkipSSLValidation).To(BeTrue()) 241 }) 242 }) 243 244 Context("when skip-ssl-validation is not required", func() { 245 BeforeEach(func() { 246 if skipSSLValidation != "" { 247 Skip("SKIP_SSL_VALIDATION is enabled") 248 } 249 }) 250 251 It("logs in without any warnings", func() { 252 command := exec.Command("cf", "api", apiURL) 253 session, err := Start(command, GinkgoWriter, GinkgoWriter) 254 Expect(err).NotTo(HaveOccurred()) 255 256 Eventually(session.Out).Should(Say("Setting api endpoint to %s...", apiURL)) 257 Consistently(session.Out).ShouldNot(Say("Warning: Insecure http API endpoint detected: secure https API endpoints are recommended")) 258 Eventually(session.Out).Should(Say("OK")) 259 Eventually(session.Out).Should(Say("Not logged in. Use 'cf login' to log in.")) 260 Eventually(session).Should(Exit(0)) 261 }) 262 263 It("sets SSL Disabled in the config file to false", func() { 264 command := exec.Command("cf", "api", apiURL, skipSSLValidation) 265 session, err := Start(command, GinkgoWriter, GinkgoWriter) 266 Expect(err).NotTo(HaveOccurred()) 267 Eventually(session).Should(Exit(0)) 268 269 rawConfig, err := ioutil.ReadFile(filepath.Join(homeDir, ".cf", "config.json")) 270 Expect(err).NotTo(HaveOccurred()) 271 272 var configFile configv3.CFConfig 273 err = json.Unmarshal(rawConfig, &configFile) 274 Expect(err).NotTo(HaveOccurred()) 275 276 Expect(configFile.SkipSSLValidation).To(BeTrue()) 277 }) 278 }) 279 280 It("sets the config file", func() { 281 command := exec.Command("cf", "api", apiURL, skipSSLValidation) 282 session, err := Start(command, GinkgoWriter, GinkgoWriter) 283 Expect(err).NotTo(HaveOccurred()) 284 Eventually(session).Should(Exit(0)) 285 286 rawConfig, err := ioutil.ReadFile(filepath.Join(homeDir, ".cf", "config.json")) 287 Expect(err).NotTo(HaveOccurred()) 288 289 var configFile configv3.CFConfig 290 err = json.Unmarshal(rawConfig, &configFile) 291 Expect(err).NotTo(HaveOccurred()) 292 293 Expect(configFile.ConfigVersion).To(Equal(3)) 294 Expect(configFile.Target).To(Equal(apiURL)) 295 Expect(configFile.APIVersion).To(MatchRegexp("\\d+\\.\\d+\\.\\d+")) 296 Expect(configFile.AuthorizationEndpoint).ToNot(BeEmpty()) 297 Expect(configFile.DopplerEndpoint).To(MatchRegexp("^wss://")) 298 Expect(configFile.RoutingEndpoint).NotTo(BeEmpty()) 299 Expect(configFile.UAAEndpoint).ToNot(BeEmpty()) 300 Expect(configFile.AccessToken).To(BeEmpty()) 301 Expect(configFile.RefreshToken).To(BeEmpty()) 302 Expect(configFile.TargetedOrganization.GUID).To(BeEmpty()) 303 Expect(configFile.TargetedOrganization.Name).To(BeEmpty()) 304 Expect(configFile.TargetedSpace.GUID).To(BeEmpty()) 305 Expect(configFile.TargetedSpace.Name).To(BeEmpty()) 306 Expect(configFile.TargetedSpace.AllowSSH).To(BeFalse()) 307 }) 308 })