diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index 8cbc7687c57d2..5eb7e80a9fd6d 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -4447,6 +4447,71 @@ func TestApplicationWebSessionsDeletedAfterLogout(t *testing.T) { require.Empty(t, collectAppSessions(context.Background())) } +func TestGetAppDetails(t *testing.T) { + ctx := context.Background() + s := newWebSuite(t) + pack := s.authPack(t, "foo@example.com") + + // Register an application called "api". + apiApp, err := types.NewAppV3(types.Metadata{ + Name: "api", + }, types.AppSpecV3{ + URI: "http://127.0.0.1:8080", + PublicAddr: "api.example.com", + }) + require.NoError(t, err) + server, err := types.NewAppServerV3FromApp(apiApp, "host", uuid.New().String()) + require.NoError(t, err) + _, err = s.server.Auth().UpsertApplicationServer(s.ctx, server) + require.NoError(t, err) + + // Register an application called "client" and have "api" required. + clientApp, err := types.NewAppV3(types.Metadata{ + Name: "client", + }, types.AppSpecV3{ + URI: "http://127.0.0.1:8080", + PublicAddr: "client.example.com", + RequiredAppNames: []string{"api"}, + }) + require.NoError(t, err) + server2, err := types.NewAppServerV3FromApp(clientApp, "host", uuid.New().String()) + require.NoError(t, err) + _, err = s.server.Auth().UpsertApplicationServer(s.ctx, server2) + require.NoError(t, err) + + clientFQDN := "client.example.com" + + tests := []struct { + name string + endpoint string + }{ + { + name: "request app details with clientName and publicAddr", + endpoint: pack.clt.Endpoint("webapi", "apps", clientFQDN, s.server.ClusterName(), clientApp.GetPublicAddr()), + }, + { + name: "request app details with fqdn only", + endpoint: pack.clt.Endpoint("webapi", "apps", clientFQDN), + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + re, err := pack.clt.Get(ctx, tc.endpoint, url.Values{}) + require.NoError(t, err) + resp := GetAppDetailsResponse{} + + require.NoError(t, json.Unmarshal(re.Bytes(), &resp)) + require.Equal(t, GetAppDetailsResponse{ + FQDN: "client.example.com", + RequiredAppFQDNs: []string{"api.example.com", "client.example.com"}, + }, resp) + }) + } +} + func TestGetWebConfig_WithEntitlements(t *testing.T) { ctx := context.Background() env := newWebPack(t, 1) diff --git a/lib/web/apps.go b/lib/web/apps.go index 2255fdc4c3234..1591eec3d6de3 100644 --- a/lib/web/apps.go +++ b/lib/web/apps.go @@ -185,16 +185,24 @@ func (h *Handler) getAppDetails(w http.ResponseWriter, r *http.Request, p httpro requiredAppNames := result.App.GetRequiredAppNames() if !isRedirectFlow { + // TODO (avatus) this would be nice if the string in the RequiredApps spec was the fqdn of the required app + // so we could skip the resolution step all together but this would break existing configs. + + // if clusterName is not supplied in the params, the initial app must have been fetched with fqdn hint only. + // We can use the clusterName of the initially resolved app + if clusterName == "" { + clusterName = result.ClusterName + } for _, required := range requiredAppNames { res, err := h.resolveApp(r.Context(), ctx, ResolveAppParams{ClusterName: clusterName, AppName: required}) if err != nil { h.log.Errorf("Error getting app details for %s, a required app for %s", required, result.App.GetName()) continue } - resp.RequiredAppFQDNs = append(resp.RequiredAppFQDNs, res.App.GetPublicAddr()) + resp.RequiredAppFQDNs = append(resp.RequiredAppFQDNs, res.FQDN) } // append self to end of required apps so that it can be the final entry in the redirect "chain". - resp.RequiredAppFQDNs = append(resp.RequiredAppFQDNs, result.App.GetPublicAddr()) + resp.RequiredAppFQDNs = append(resp.RequiredAppFQDNs, result.FQDN) } return resp, nil