Create and expose the portal
Now that you decided on your portal configuration, you can create your developer portal and make it available to your users.
Before you begin
- Deploy sample REST APIs and bundle them to API products.
- Prepare usage plans.
- Decide on your developer portal configuration. This guide assumes that you want to include the tracks and petstore API products in your developer portal. The tracks API is publicly available, and the petstore API is visible only if you are successfully authenticated and authorized.
Create and expose the developer portal
In this guide, you create your portal resource and expose the portal backend so that you can interact with your portal by using your terminal.
-
Create the developer portal. The following portal resource creates a developer portal for the
developer.example.com
host and includes all API products with theportal: dev-portal
label. If you followed the examples in Decide on your portal configuration, the tracks and petstore API products are served by this portal resource.kubectl apply -f- <<EOF apiVersion: apimanagement.gloo.solo.io/v2 kind: Portal metadata: name: developer-portal namespace: gloo-mesh-addons spec: visibility: public: true privateAPILabels: portal-visibility: private domains: - "developer.example.com" portalBackendSelectors: - selector: labels: app: gloo-mesh-portal-server usagePlans: - name: bronze displayName: "Bronze Plan" description: "A basic usage plan" - name: silver description: "A better usage plan" - name: gold description: "The best usage plan!" apis: - labels: portal: dev-portal EOF
-
Verify that the internal
PortalConfig
resource is created for your portal. By default, this resource is created in thegloo-mesh-addons
namespace.kubectl get portalconfigs -n gloo-mesh-addons -o yaml
Example output: Notice that the stitched schema is used, as well as the portal metadata that you set in the route table.
apiVersion: v1 items: - apiVersion: internal.gloo.solo.io/v2 kind: PortalConfig metadata: annotations: cluster.solo.io/cluster: cluster-1 creationTimestamp: "2023-04-06T21:30:41Z" generation: 1 labels: context.mesh.gloo.solo.io/cluster: cluster-1-portal context.mesh.gloo.solo.io/namespace: gloo-mesh-gateways context.mesh.gloo.solo.io/workspace: cluster-1-portal gloo.solo.io/parent_cluster: cluster-1-portal gloo.solo.io/parent_group: "" gloo.solo.io/parent_kind: Namespace gloo.solo.io/parent_name: gloo-mesh-gateways gloo.solo.io/parent_namespace: "" gloo.solo.io/parent_version: v1 reconciler.mesh.gloo.solo.io/name: translator name: developer-portal-gloo-mesh-addons-cluster-1-portal namespace: gloo-mesh-addons resourceVersion: "1985686" uid: 59fe5508-d839-4720-b6ae-59347664e3bb spec: apis: - apiSchema: cluster: cluster-1-portal name: tracks-rt-stitched-openapi-cluster-1-portal-gloo-mesh-gateways-cluster-1-portal namespace: gloo-mesh-addons contact: support@example.com description: REST API for Catstronauts to retrieve data for tracks, authors and modules. license: license info routeTable: cluster: cluster-1-portal name: tracks-rt namespace: gloo-mesh-gateways termsOfService: You must authenticate to use this API! And other Terms of Service. title: Catstronauts REST API - apiSchema: cluster: cluster-1-portal name: petstore-rt-stitched-openapi-cluster-1-portal-gloo-mesh-gateways-cluster-1-portal namespace: gloo-mesh-addons contact: support@example.com description: Totally awesome API for all things pets! license: license info routeTable: cluster: cluster-1-portal name: petstore-rt namespace: gloo-mesh-gateways termsOfService: You must authenticate to use this API! And other Terms of Service. title: Petstore REST API domains: - developer.example.com portalRef: cluster: cluster-1-portal name: developer-portal namespace: gloo-mesh-addons public: true kind: List metadata: resourceVersion: "" selfLink: ""
-
Create a virtual gateway that you use to expose the developer portal. The following example selects the default ingress gateway that you deployed during your Gloo Platform installation. For more examples such as HTTPS/TLS, see Configure gateway listeners.
kubectl apply -f- <<EOF apiVersion: networking.gloo.solo.io/v2 kind: VirtualGateway metadata: name: istio-ingressgateway-portal namespace: gloo-mesh-gateways spec: listeners: - allowedRouteTables: - host: developer.example.com http: {} port: number: 80 workloads: - selector: cluster: $CLUSTER_NAME labels: istio: ingressgateway EOF
-
Create a route table for the developer portal. The following route table creates routes for all the portal APIs so that you can interact with your developer portal.
kubectl apply -f - <<EOF apiVersion: networking.gloo.solo.io/v2 kind: RouteTable metadata: name: dev-portal-rt namespace: gloo-mesh-gateways spec: hosts: - developer.example.com virtualGateways: - name: istio-ingressgateway-portal namespace: gloo-mesh-gateways defaultDestination: port: number: 8080 ref: name: gloo-mesh-portal-server namespace: gloo-mesh-addons cluster: $CLUSTER_NAME http: # # Portal server routes that require authentication. # - forwardTo: {} name: authn labels: oauth: "true" # Use this label to apply an OAuth external auth policy route: portal-api matchers: # # /v1/me - uri: prefix: /v1/me method: OPTIONS - uri: prefix: /v1/me method: GET headers: - name: Authorization value: "Bearer.*" regex: true # # /v1/apis - uri: prefix: /v1/apis method: GET headers: - name: Authorization value: "Bearer.*" regex: true # # /v1/usage-plans - uri: prefix: /v1/usage-plans method: GET headers: - name: Authorization value: "Bearer.*" regex: true # # /v1/api-keys - uri: prefix: /v1/api-keys method: GET headers: - name: Authorization value: "Bearer.*" regex: true - uri: prefix: /v1/api-keys method: POST headers: - name: Authorization value: "Bearer.*" regex: true - uri: prefix: /v1/api-keys method: DELETE headers: - name: Authorization value: "Bearer.*" regex: true # # Portal server routes that are public and do not require authentication. # - forwardTo: {} name: no-auth labels: route: portal-api matchers: - uri: prefix: /v1/apis method: GET - uri: prefix: /v1/usage-plans method: GET - uri: prefix: /v1/api-keys method: GET # # Allow OPTION requests without authentication. # - uri: prefix: /v1/api-keys method: OPTIONS - uri: prefix: /v1/usage-plans method: OPTIONS - uri: prefix: /v1/apis method: OPTIONS EOF
-
Send a request to the developer portal to list the APIs that you have access to. Note that because the petstore API is set to private, only the tracks API is returned in your CLI output. To view the private petstore APIs, you must set up authentication and authorization. For more information, see Secure the portal.
curl -vik --resolve developer.example.com:80:$INGRESS_GW_IP http://developer.example.com:80/v1/apis
Example output:
* Mark bundle as not supporting multiuse < HTTP/1.1 200 OK HTTP/1.1 200 OK < content-type: application/json content-type: application/json < date: Fri, 14 Apr 2023 13:57:02 GMT date: Fri, 14 Apr 2023 13:57:02 GMT < content-length: 387 content-length: 387 < x-envoy-upstream-service-time: 0 x-envoy-upstream-service-time: 0 < server: istio-envoy server: istio-envoy < [{"apiProductDisplayName":"Catstronauts Course Tracks","apiProductId":"tracks","apiVersions":[{"apiId":"tracks-v1","apiVersion":"v1","contact":"support@example.com","customMetadata":{"compatibility":"None"},"description":"REST API for Catstronauts to retrieve data for tracks, authors and modules.","license":"License info, such as MIT","lifecycle":"Supported","termsOfService":"You must authenticate to use this API! And other Terms of Service.","title":"Catstronauts REST API","usagePlans":["bronze","gold","silver"]}]},{"apiProductDisplayName":"Pet Store","apiProductId":"petstore","apiVersions":[{"apiId":"petstore-v1","apiVersion":"v1","contact":"support@example.com","customMetadata":{"compatibility":"None"},"description":"Totally awesome API for all things pets!","license":"License info, such as MIT","lifecycle":"Supported","termsOfService":"You must authenticate to use this API! And other Terms of Service.","title":"Pet Store REST API","usagePlans":["bronze","gold","silver"]}]}] * Connection #0 to host developer.example.com left intact
The /me
and /api-keys
paths are protected even if you set API product visibility to public. These API paths cannot be accessed until a user is authenticated with an OIDC provider. For more information, see Set up external authentication.
Next steps
You can continue to use your portal in several ways:
- Create a frontend for the developer portal.
- Secure the portal, either along your backend or frontend routes.