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  })