solo-io / gloo-portal-issues

Public tracker for issues related to Gloo Portal
https://docs.solo.io/gloo-portal/latest/
1 stars 3 forks source link

Allow preserving custom `securitySchemes` in a portal #137

Closed marcogschmidt closed 2 years ago

marcogschmidt commented 2 years ago

Problem summary

In order to allow users to try out secured APIs in a portal, Gloo Portal needs to add securitySchemes/security fields to the OpenAPI spec of the API based on the UsagePlans that are defined on.

The change was made to allows administrators (who usually manage Environments) to prevent arbitrary security config defined the individual APIdocs (that are usually managed by app teams) from appearing it to the portal app.

The new behavior works for most users, but there are scenarios where users want the securitySchemes/security config from APIDocs to appear alongside the one generated based on UsagePlan (e.g. because they have custom auth flows that Gloo Portal cannot manage).

To reproduce

To verify this behavior, first install Gloo Portal 0.5.2:

# Install a compatible Gloo Edge version 
glooctl install gateway enterprise --license-key $GLOO_LICENSE_KEY --version v1.7.0

# Helm value to install Gloo Portal on top of Edge
cat << EOF > values.yaml
licenseKey:
  secretRef:
    name: license
    namespace: gloo-system
    key: license-key
gloo:
  enabled: true
EOF

# Install Gloo Portal
kubectl create namespace dev-portal
helm upgrade --install dev-portal dev-portal/dev-portal -n dev-portal --values values.yaml --version 0.5.2

Then apply the following resources (note that these are in a format that will not work with recent versions of Gloo Portal):

Click to expand ```yaml apiVersion: devportal.solo.io/v1alpha1 kind: APIDoc metadata: name: petstore-schema namespace: default spec: openApi: content: inlineString: |2 openapi: "3.0.0" info: version: 1.0.0 title: Swagger Petstore license: name: MIT servers: - url: http://petstore.swagger.io/v1 security: - foo-auth: [] paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: '200': description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" post: summary: Create a pet operationId: createPets tags: - pets responses: '201': description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: '200': description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pet" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: securitySchemes: foo-auth: description: Foo auth (we want to disply this in the portal UI) name: foo in: header type: apiKey schemas: Pet: type: object required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string Pets: type: array items: $ref: "#/components/schemas/Pet" Error: type: object required: - code - message properties: code: type: integer format: int32 message: type: string --- apiVersion: devportal.solo.io/v1alpha1 kind: APIProduct metadata: name: petstore-product namespace: default spec: displayInfo: description: Petstore Product title: Petstore Product versions: - name: v1 apis: - apiDoc: name: petstore-schema namespace: default defaultRoute: inlineRoute: backends: - kube: name: petstore namespace: default port: 8080 tags: stable: { } --- apiVersion: devportal.solo.io/v1alpha1 kind: Environment metadata: name: dev namespace: default spec: domains: - api.example.com - api.example.com:32000 displayInfo: description: This environment is meant for developers to deploy and test their APIs. displayName: Development apiProducts: - name: petstore-product namespace: default plans: - authPolicy: apiKey: { } displayName: API usage plan managed by Gloo Portal name: managed-api-key rateLimit: requestsPerUnit: 3 unit: MINUTE publishedVersions: - name: v1 --- apiVersion: devportal.solo.io/v1alpha1 kind: Portal metadata: name: petstore-portal namespace: default spec: displayName: Petstore Portal description: The Gloo Portal for the Petstore API banner: fetchUrl: https://i.imgur.com/EXbBN1a.jpg favicon: fetchUrl: https://i.imgur.com/QQwlQG3.png primaryLogo: fetchUrl: https://i.imgur.com/hjgPMNP.png domains: - localhost:8080 - localhost publishedEnvironments: - name: dev namespace: default --- apiVersion: devportal.solo.io/v1alpha1 kind: User metadata: name: alice namespace: default spec: accessLevel: apiProducts: - environments: - name: dev namespace: default plans: - api-key-up name: petstore-product namespace: default portals: - name: petstore-portal namespace: default basicAuth: passwordSecretKey: password passwordSecretName: alice-password passwordSecretNamespace: default username: alice --- apiVersion: v1 data: # Password is: password1! password: JDJhJDEwJFpwL3EzeVdhQmhVd0lWUlhiMkFPWnUuQkQ1TnN6Y3g5d3F2SU1yQldHdzc1Q2ViSGVzNnBX kind: Secret metadata: name: alice-password namespace: default type: Opaque ```

If you now port forward the portal pod,

kubectl port-forward -n dev-portal deploy/dev-portal 8080

open localhost:8080 in your browser, log in (alice/password1!), and check the API documentation you should see two authorizations: image

If you now upgrade to 0.5.3 you should see only one authorization (the one generated by Gloo Portal based on the UsagePlans) on the same page:

helm upgrade --install dev-portal dev-portal/dev-portal -n dev-portal --values values.yaml --version 0.5.3

image

Proposed solution

A simple solution would be to allow users to toggle the behavior between overwrite and merge. This could be achieved on a per-Environment basis by adding a flag to the Environment spec:

apiVersion: portal.gloo.solo.io/v1beta1
kind: Environment
metadata:
  name: dev
  namespace: default
spec:
  domains:
  - api.example.com
  apiProducts: []
  # If set to `true`, we will preserve the user-defined security config from the APIDoc OpenAPI specs
  preserveApiDocSecurity: true

If omitted, the field would default to false so we maintain backwards-compatibility.

bewebi commented 2 years ago

I've reproduced the issue on Portal 1.2 with Gloo 1.10 with these resources security-schemes-resources.tar.gz

bewebi commented 2 years ago

solo-io/dev-portal#2143 merged and will be included in the next 1.2 beta release

d4nj0nes-p commented 2 years ago

@bewebi - just coming to test this. I have set preserveApiDocSecurity to enable being able to set the value and the custom token field is available for me to enter a value in portal authorizations. However the header is never sent with the request. Only the users api-key header is included. Am I missing some other necessary confgiuration?