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