github.com/loafoe/cli@v7.1.0+incompatible/integration/helpers/fake_server.go (about)

     1  package helpers
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  	"time"
     8  
     9  	. "github.com/onsi/gomega"
    10  	. "github.com/onsi/gomega/gexec"
    11  	. "github.com/onsi/gomega/ghttp"
    12  )
    13  
    14  const (
    15  	DefaultV2Version         string = "2.131.0"
    16  	DefaultV3Version         string = "3.66.0"
    17  	DefaultAuthorizationPath string = ""
    18  )
    19  
    20  // StartAndTargetMockServerWithAPIVersions starts and targets a server with the given V2 and V3
    21  // API versions.
    22  func StartAndTargetMockServerWithAPIVersions(v2Version string, v3Version string) *Server {
    23  	server := StartMockServerWithAPIVersions(v2Version, v3Version)
    24  	Eventually(CF("api", server.URL(), "--skip-ssl-validation")).Should(Exit(0))
    25  
    26  	return server
    27  }
    28  
    29  // StartMockServerWithMinimumCLIVersion starts a server with the default V2 and V3
    30  // API versions and the given minimum CLI version.
    31  func StartMockServerWithMinimumCLIVersion(minCLIVersion string) *Server {
    32  	return startServerWithVersions(DefaultV2Version, DefaultV3Version, &minCLIVersion, DefaultAuthorizationPath)
    33  }
    34  
    35  // StartMockServerWithAPIVersions starts a server with the given V2 and V3
    36  // API versions
    37  func StartMockServerWithAPIVersions(v2Version string, v3Version string) *Server {
    38  	return startServerWithVersions(v2Version, v3Version, nil, DefaultAuthorizationPath)
    39  }
    40  
    41  // StartMockServerWithAPIVersions starts a server with the given V2 and V3
    42  // API versions
    43  func StartMockServerWithCustomAuthorizationEndpoint(authorizationPath string) *Server {
    44  	return startServerWithVersions(DefaultV2Version, DefaultV3Version, nil, authorizationPath)
    45  }
    46  
    47  func startServerWithVersions(v2Version string, v3Version string, minimumCLIVersion *string, authorizationPath string) *Server {
    48  	server := NewTLSServer()
    49  
    50  	rootResponse := fmt.Sprintf(`{
    51     "links": {
    52        "self": {
    53           "href": "%[1]s"
    54        },
    55        "cloud_controller_v2": {
    56           "href": "%[1]s/v2",
    57           "meta": {
    58              "version": "%[2]s"
    59           }
    60        },
    61        "cloud_controller_v3": {
    62           "href": "%[1]s/v3",
    63           "meta": {
    64              "version": "%[3]s"
    65           }
    66        },
    67        "network_policy_v0": {
    68           "href": "%[1]s/networking/v0/external"
    69        },
    70        "network_policy_v1": {
    71           "href": "%[1]s/networking/v1/external"
    72        },
    73        "uaa": {
    74           "href": "SHOULD-NOT-BE-USED-FOR-LOGGING-IN.com"
    75        },
    76        "login": {
    77           "href": "%[1]s"
    78        },
    79        "logging": {
    80           "href": "wss://unused:443"
    81        },
    82        "log_cache": {
    83           "href": "%[1]s"
    84        },
    85        "app_ssh": {
    86           "href": "unused:2222",
    87           "meta": {
    88              "host_key_fingerprint": "unused",
    89              "oauth_client": "ssh-proxy"
    90           }
    91        }
    92     }
    93   }`, server.URL(), v2Version, v3Version)
    94  
    95  	v2InfoResponse := struct {
    96  		APIVersion            string  `json:"api_version"`
    97  		AuthorizationEndpoint string  `json:"authorization_endpoint"`
    98  		MinCLIVersion         *string `json:"min_cli_version"`
    99  	}{
   100  		APIVersion:            v2Version,
   101  		AuthorizationEndpoint: server.URL() + authorizationPath,
   102  		MinCLIVersion:         minimumCLIVersion}
   103  
   104  	server.RouteToHandler(http.MethodGet, "/v2/info", RespondWithJSONEncoded(http.StatusOK, v2InfoResponse))
   105  
   106  	v3Response := strings.Replace(`{"links": {
   107  			"apps": {
   108  				"href": "SERVER_URL/v3/apps"
   109  			},
   110  			"organizations": {
   111  				"href": "SERVER_URL/v3/organizations"
   112  			},
   113  			"spaces": {
   114  				"href": "SERVER_URL/v3/spaces"
   115  			}
   116  		}}`, "SERVER_URL", server.URL(), -1)
   117  
   118  	server.RouteToHandler(http.MethodGet, "/v3", func(res http.ResponseWriter, req *http.Request) {
   119  		res.WriteHeader(http.StatusOK)
   120  		res.Write([]byte(v3Response))
   121  	})
   122  
   123  	server.RouteToHandler(http.MethodGet, authorizationPath+"/login", func(res http.ResponseWriter, req *http.Request) {
   124  		res.WriteHeader(http.StatusOK)
   125  		res.Write([]byte(`{"links":{}}`))
   126  	})
   127  
   128  	server.RouteToHandler(http.MethodGet, "/", func(res http.ResponseWriter, req *http.Request) {
   129  		res.WriteHeader(http.StatusOK)
   130  		res.Write([]byte(rootResponse))
   131  	})
   132  
   133  	return server
   134  }
   135  
   136  // AddMfa adds a mock handler to the given server which returns a login response and a 200 status code
   137  // on GET requests to the /login endpoint. It adds another mock handler to validate the given password and MFA token
   138  // upon POST requests to /oauth/token.
   139  func AddMfa(server *Server, password string, mfaToken string) {
   140  	getLoginResponse := fmt.Sprintf(`{
   141      "app": {
   142          "version": "4.28.0"
   143      },
   144      "showLoginLinks": true,
   145      "links": {
   146          "uaa": "%[1]s",
   147          "passwd": "/forgot_password",
   148          "login": "%[1]s",
   149          "register": "/create_account"
   150      },
   151      "zone_name": "uaa",
   152      "entityID": "some-host-name.example.com",
   153      "commit_id": "8917980",
   154      "idpDefinitions": {},
   155      "prompts": {
   156          "username": [
   157              "text",
   158              "Email"
   159          ],
   160          "password": [
   161              "password",
   162              "Password"
   163          ],
   164          "passcode": [
   165              "password",
   166              "Temporary Authentication Code ( Get one at %[1]s/passcode )"
   167          ],
   168          "mfaCode": [
   169              "password",
   170              "MFA Code ( Register at %[1]s )"
   171          ]
   172      },
   173      "timestamp": "2019-02-19T18:08:02+0000"
   174  }`, server.URL())
   175  
   176  	server.RouteToHandler(http.MethodGet, "/login",
   177  		RespondWith(http.StatusOK, getLoginResponse),
   178  	)
   179  
   180  	server.RouteToHandler(http.MethodPost, "/oauth/token", makeMFAValidator(password, mfaToken))
   181  
   182  }
   183  
   184  func makeMFAValidator(password string, mfaToken string) http.HandlerFunc {
   185  	return func(res http.ResponseWriter, req *http.Request) {
   186  		Expect(req.ParseForm()).To(Succeed())
   187  		rightPassword := len(req.Form["password"]) == 1 && req.Form["password"][0] == password
   188  		rightCode := len(req.Form["mfaCode"]) == 1 && req.Form["mfaCode"][0] == mfaToken
   189  
   190  		if rightPassword && rightCode {
   191  			res.WriteHeader(http.StatusOK)
   192  			res.Write([]byte(`{
   193      "access_token": "some-access-token",
   194      "token_type": "bearer",
   195      "id_token": "some-id-token",
   196      "refresh_token": "some-refresh-token",
   197      "expires_in": 599,
   198      "scope": "openid routing.router_groups.write scim.read cloud_controller.admin uaa.user routing.router_groups.read cloud_controller.read password.write cloud_controller.write network.admin doppler.firehose scim.write",
   199      "jti": "66e46003f28e44c8a6582f6d6e44753f"
   200  }`))
   201  			return
   202  		}
   203  		res.WriteHeader(http.StatusUnauthorized)
   204  	}
   205  }
   206  
   207  // AddLoginRoutes adds a mock handler to the given server which returns an access token and a 200 status code
   208  // on POST requests to /oauth/token.
   209  func AddLoginRoutes(s *Server) {
   210  	s.RouteToHandler("POST", "/oauth/token", RespondWith(http.StatusOK,
   211  		fmt.Sprintf(`{
   212  			"access_token": "%s",
   213  			"expires_in": 599,
   214  			"id_token": "some-other-token",
   215  			"jti": "some-other-string",
   216  			"refresh_token": "some-refresh-token",
   217  			"scope": "openid routing.router_groups.write scim.read cloud_controller.admin uaa.user routing.router_groups.read cloud_controller.read password.write cloud_controller.write network.admin doppler.firehose scim.write",
   218  			"token_type": "bearer"
   219  		 }`, BuildTokenString(time.Now().Add(599*time.Second)))),
   220  	)
   221  }