Skip to content
You are viewing the latest documentation for Solo Enterprise for kgateway. To access the documentation for older versions, use the version switcher.

Get started with portal

Page as Markdown

Create your first portal web server and expose the httpbin API on it.

This guide must be completed by a Portal admin.

Portal is a developer portal for Solo Enterprise for kgateway that lets API consumers discover, browse, and interact with APIs. The portal renders an API catalog from OpenAPI specifications and provides self-service features, including team management, app registration, and API key provisioning.

About this guide

In this guide, you learn how to set up your first portal web server and expose the httpbin API in your API catalog. To interact with the portal, you create a frontend app that allows you to view the APIs that are exposed in the API catalog.

Before you begin

Follow the Get started guide to install Solo Enterprise for kgateway.

Set up a portal

Install the portal controller and set up your first portal web server.

  1. Get a portal license and set it as an environment variable. If you do not have one, contact an account representative.

    export PORTAL_LICENSE_KEY=<portal-license-key>
  2. Install the portal CRDs.

    helm upgrade -i portal-crds \
     oci://us-docker.pkg.dev/solo-public/enterprise-kgateway/charts/portal-crds \
     --version 2.2.4 \
     --namespace portal-system \
     --create-namespace
  3. Install the portal controller.

    helm upgrade -i portal \
      oci://us-docker.pkg.dev/solo-public/enterprise-kgateway/charts/portal \
      --version 2.2.4 \
      --namespace portal-system \
      --set licensing.licenseKey=$PORTAL_LICENSE_KEY
  4. Verify that the controller is up and running. The controller watches Portal custom resources.

    kubectl get pods -n portal-system

    Example output:

    NAME                                 READY   STATUS    RESTARTS   AGE
    portal-controller-5b98557f9b-kz56c   1/1     Running   0          45s
  5. Create a PortalParameters resource.

    PortalParameters control the operational configuration of the portal web server, such as the data store that you want to use. For testing purposes, you can use the built-in container storage that is used in this example. Note that data is removed when the portal web server restarts. To use a persistent data storage solution, such as PostgresQL, see the Portal database install guide.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: PortalParameters
    metadata:
      name: portal-params
      namespace: default
    spec:
      store:
        memory: {}
    EOF
  6. Create the portal.

    After you create the resource, the portal controller spins up a portal web server for you. The portal web server represents the portal backend. To interact with your portal and share APIs with users, you must create a frontend app for your portal as shown in later steps of this tutorial. Note that no APIProducts are referenced in the portal yet. You populate APIProducts later.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: Portal
    metadata:
      name: my-portal
      namespace: default
    spec:
      parametersRef:
        name: portal-params
      visibility:
        public: true
      apiProductRefs: []
    EOF
    SettingDescription
    parametersRefReferences the PortalParameters resource that you created earlier.
    visibility.publicWhen set to true, the API catalog in the portal is accessible without authentication.
    apiProductRefsList of ApiProduct references to include in the API catalog. In this example, no APIProducts are referenced yet. You populate the portal catalog later.
  7. Verify that a portal web server is created for you.

    kubectl get deployment portal-my-portal -n default
    kubectl get service portal-my-portal -n default

    Example output:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    portal-my-portal   1/1     1            1           2m51s
    NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
    portal-my-portal   ClusterIP   10.96.78.9   <none>        8080/TCP   2m51s

Expose the portal

Create a Gateway for your portal web server that serves requests for the portal.example.com sample domain.

  1. Create a Gateway.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: portal-gateway
      namespace: default
    spec:
      gatewayClassName: enterprise-kgateway
      listeners:
      - name: http
        port: 8080
        protocol: HTTP
        allowedRoutes:
          namespaces:
            from: All
    EOF
  2. Create an HTTPRoute to route traffic to the portal. The portal backend exposes the following /v1/ endpoints.

    • /v1/api-products: API catalog (public)
    • /v1/metadata: Credential validation
    • /v1/me, /v1/users: User management (requires auth)
    • /v1/teams: Team management (requires auth)
    • /v1/apps: App registration and API key provisioning (requires auth)
    • /v1/subscriptions: API subscription management (requires auth)
    • /v1/oauth-credentials: OAuth credential management (requires auth)
    • /v1/login, /v1/logout: OIDC redirect endpoints (when using OIDC auth)

    For a minimal public catalog, expose only the /v1/api-products and /v1/metadata paths. To keep the configuration simple, you can expose all /v1/ paths as shown in this exmaple.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: my-portal-backend
      namespace: default
    spec:
      parentRefs:
      - name: portal-gateway
        namespace: default
      hostnames:
      - "portal.example.com"
      rules:
      - filters: 
        - type: CORS
          cors:
            allowHeaders:
            - "*"
            allowMethods:
            - GET
            - POST
            - PUT
            - DELETE
            - OPTIONS
            allowOrigins:
            - "*"
        matches:
        - path:
            type: PathPrefix
            value: /v1/
        backendRefs:
        - name: portal-my-portal
          namespace: default
          port: 8080
    EOF

Deploy the portal frontend

To interact with the portal backend and share APIs with users, create a frontend app for your portal. You can use your own frontend app or deploy the app that is provided by Solo.io as shown in this tutorial.

  1. Create the portal frontend. Make sure to set the VITE_PORTAL_SERVER_URL environment variable to the hostname and path prefix that you configured in the Gateway and HTTPRoute for your portal backend.

    kubectl apply -f- <<EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: portal-ui
      namespace: default
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: portal-ui
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: portal-ui
      template:
        metadata:
          labels:
            app: portal-ui
        spec:
          serviceAccountName: portal-ui
          securityContext:
            runAsNonRoot: true
            runAsUser: 10101
          containers:
          - name: portal-ui
            image: gcr.io/solo-public/docs/portal-frontend:v0.1.8
            imagePullPolicy: IfNotPresent
            ports:
            - name: http
              containerPort: 4000
              protocol: TCP
            env:
            - name: VITE_PORTAL_SERVER_URL
              value: "http://portal.example.com:8080/v1"
            livenessProbe:
              httpGet:
                path: /
                port: http
              initialDelaySeconds: 10
              periodSeconds: 10
            readinessProbe:
              httpGet:
                path: /
                port: http
              initialDelaySeconds: 5
              periodSeconds: 5
            resources:
              requests:
                cpu: 100m
                memory: 128Mi
              limits:
                cpu: 500m
                memory: 512Mi
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
              capabilities:
                drop:
                - ALL
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: portal-ui
      namespace: default
    spec:
      type: ClusterIP
      ports:
      - port: 4000
        targetPort: http
        protocol: TCP
        name: http
      selector:
        app: portal-ui
    EOF
    The demo frontend displays a Login button by default. Without any OIDC configuration, an Access Issues error is deplayed when you click the button. This is expected. The public API catalog works without authentication. To enable login, you need to deploy an identity provider, such Keycloak, and set the VITE_APPLIED_OIDC_AUTH_CODE_CONFIG, VITE_OIDC_AUTH_CODE_CONFIG_CALLBACK_PATH, and VITE_OIDC_AUTH_CODE_CONFIG_LOGOUT_PATH environment variables on the frontend.
  2. Wait for the frontend app to be deployed.

    kubectl rollout status deploy/portal-ui
  3. Create an HTTPRoute to route traffic to the frontend.

    The frontend route uses a / catch-all prefix path. Note that the Kubernetes Gateway API evaluates routes by specificity. Because of that, more specific /v1/* backend routes take precedence. The frontend route serves all other paths, including the UI assets or index.html file.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: my-portal-frontend
      namespace: default
    spec:
      parentRefs:
      - name: portal-gateway
        namespace: default
      hostnames:
      - "portal.example.com"
      rules:
      - filters:
        - type: CORS
          cors:
            allowHeaders:
            - "*"
            allowMethods:
            - GET
            - POST
            - PUT
            - DELETE
            - OPTIONS
            allowOrigins:
            - "*"
        matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: portal-ui
          namespace: default
          port: 4000
    EOF
  4. Port-forward the gateway on port 8080

    kubectl port-forward -n default svc/portal-gateway 8080:8080
  5. Edit the /etc/hosts file on your local machine to map the portal.example.com domain to localhost. This step is required in local test setups to access the portal frontend from your web browser. If you used a registered domain that you own to expose the portal, this step is not required and can be skipped.

    sudo nano /etc/hosts

    Add the following entry:

    127.0.0.1 portal.example.com
  6. In a web browser, open the portal UI on the domain that you set up, such as http://portal.example.com:8080/. You see the portal UI with an empty API catalog.

Add API products

Now that you have a portal up and running, you can start exposing APIs on it. This example exposes the httpbin API as an API product.

  1. Deploy the httpbin sample app.

    kubectl apply -f- <<EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
      namespace: default
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
      template:
        metadata:
          labels:
            app: httpbin
        spec:
          serviceAccountName: httpbin
          containers:
          - name: httpbin
            image: mccutchen/go-httpbin:v2.15.0
            ports:
            - containerPort: 8080
            env:
            - name: PORT
              value: "8080"
            resources:
              requests:
                cpu: 50m
                memory: 64Mi
              limits:
                cpu: 200m
                memory: 128Mi
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      namespace: default
    spec:
      type: ClusterIP
      ports:
      - port: 8080
        targetPort: 8080
        name: http
      selector:
        app: httpbin
    EOF
  2. Create an HTTPRoute for the httpbin app. The app is exposed under the api.example.com sample domain. You can use this domain as an umbrella for all your APIs that you want to expose in the portal. The URLRewrite filter removes the /httpbin prefix before forwarding the request to the backend. For example, a request to /httpbin/get is rewritten to /get so that the httpbin service can serve it properly.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-route
      namespace: default
    spec:
      parentRefs:
      - name: portal-gateway
        namespace: default
      hostnames:
      - "api.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /httpbin
        filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
        backendRefs:
        - name: httpbin
          port: 8080
    EOF
  3. Create an ApiDoc.

    An ApiDoc describes and pairs the OpenAPI schema with the backend service that serves this schema. To pair an ApiDoc with a service, you use the servedBy field. The following ApiDoc describes the /get, /headers, and /status/{code} API endpoints of the httpbin API. Note that the API endpoints are manually added to the ApiDoc. You can also fetch the schema from a URL or an endpoint that is exposed by the service. For more information, see Create ApiDocs.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: ApiDoc
    metadata:
      name: httpbin-apidoc
      namespace: default
    spec:
      source:
        manual:
          content: |
            {
              "openapi": "3.0.0",
              "info": {
                "title": "HTTPBin API",
                "version": "1.0.0",
                "description": "A simple HTTP request/response service"
              },
              "paths": {
                "/get": {
                  "get": {
                    "summary": "Returns GET data",
                    "responses": {
                      "200": { "description": "Successful response with request details" }
                    }
                  }
                },
                "/headers": {
                  "get": {
                    "summary": "Returns request headers",
                    "responses": {
                      "200": { "description": "Successful response with headers" }
                    }
                  }
                },
                "/status/{code}": {
                  "get": {
                    "summary": "Returns given HTTP status code",
                    "parameters": [
                      {
                        "name": "code",
                        "in": "path",
                        "required": true,
                        "schema": { "type": "integer" }
                      }
                    ],
                    "responses": {
                      "200": { "description": "Successful response" }
                    }
                  }
                }
              }
            }
      servedBy:
        name: httpbin
        namespace: default
        port: 8080
    EOF
  4. Create an ApiProduct.

    An ApiProduct is a logical API product that can describe one or more versions of an API that you want to expose in the portal API catalog. Each version references the HTTPRoute that serves this version of the API. The portal controller automatically discovers the paired ApiDocs resource to display available API endpoints for that version in the portal frontend. When you create an ApiProduct, version-specific schema and metadata information is automatically stitched together into one schema and added to another ApiDocs resource.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: ApiProduct
    metadata:
      name: httpbin-api
      namespace: default
    spec:
      id: httpbin
      displayName: "HTTPBin API"
      customMetadata:
        category: "Utilities"
      versions:
      - name: v1
        targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: httpbin-route
        openApiMetadata:
          title: "HTTPBin API"
          description: "A simple HTTP request/response service for testing"
    EOF
  5. Add the ApiProduct to the portal.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: Portal
    metadata:
      name: my-portal
      namespace: default
    spec:
      parametersRef:
        name: portal-params
      visibility:
        public: true
      apiProductRefs:
      - name: httpbin-api
    EOF
  6. Verify that all portal resources are ready. Note that you see two ApiDocs resources, the httpbin-apidoc one that you created and httpbin-api-v1 that was automatically created by the portal controller and contains the stitched schema for all versions of the httpbin API that you want to expose.

    kubectl get apidoc,apiproduct,portal,portalconfig,portalparameters -n default

    Example output:

    NAME                                         SOURCE   READY
    apidoc.portal.solo.io/httpbin-apidoc         Manual   True
    apidoc.portal.solo.io/httpbin-api-v1         Stitched True
    
    NAME                                     ID       DISPLAY NAME   READY
    apiproduct.portal.solo.io/httpbin-api    httpbin  HTTPBin API    True
    
    NAME                                 PROGRAMMED
    portal.portal.solo.io/my-portal      True
  7. Edit the /etc/hosts file again to map the api.example.com sample domain to localhost on your local machine. This step is required in local test setups so that you can access the httpbin API via the portal frontend app in your web browser. If you used a registered domain, this step is not required and can be skipped.

    sudo nano /etc/hosts

    Add the following entry:

    127.0.0.1 portal.example.com api.example.com
  8. Open the portal UI such as http://portal.example.com:8080/ in a browser and select APIs from the navbar. Verify that you see the HTTPBin API in the portal catalog.

  9. Click the HTTPBin API card to drill into the API. By default, the API opens the Redocly view. You can optionally switch to the Swagger view to try out the API endpoints that you exposed.

Next

Now that you have your first API exposed on your portal, check out the following guides to further build out your portal.

Was this page helpful?