Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Authpolicy from OpenAPI 3.0.X #46

Merged
merged 9 commits into from
Nov 28, 2023

Conversation

eguzki
Copy link
Collaborator

@eguzki eguzki commented Nov 16, 2023

What

New command kuadrantctl generate kuadrant authpolicy to create kuadrant Auth Policy from OpenAPI Specification (OAS) 3.x powered with kuadrant extensions

openIdConnect type

This initial version of the command only generates AuhPolicy when there is at least one security requirement referencing the Security Scheme Object which type is openIdConnect.

Example

paths:
  /dog:
    get: 
      x-kuadrant:  
        backendRefs:
          - name: petstore
            port: 80
            namespace: petstore
      operationId: "getDog"
      security:
        - securedDog: []
      responses:
        405:
          description: "invalid input"
components:
  securitySchemes:
    securedDog:
      type: openIdConnect
      openIdConnectUrl: https://example.com/.well-known/openid-configuration

Running the command

kuadrantctl generate kuadrant authpolicy --oas ./petstore-openapi.yaml  | yq -P

The generated authpolicy

kind: AuthPolicy
apiVersion: kuadrant.io/v1beta2
metadata:
  name: petstore
  namespace: petstore
  creationTimestamp: null
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: petstore
    namespace: petstore
  routeSelectors:
    - matches:
        - path:
            type: Exact
            value: /api/v1/dog
          method: GET
  rules:
    authentication:
      getDog:
        credentials: {}
        jwt:
          issuerUrl: https://example.com/.well-known/openid-configuration
        routeSelectors:
          - matches:
              - path:
                  type: Exact
                  value: /api/v1/dog
                method: GET

Verification Steps

  • [Optional] Setup SSO service supporting OIDC. For this example, we will be using keycloak.
    • Create a new realm petstore
    • Create a client petstore. In the Client Protocol field, select openid-connect.
    • Configure client settings. Access Type to public. Direct Access Grants Enabled to ON (for this example password will be used directly to generate the token).
    • Add a user to the realm
      • Click the Users menu on the left side of the window. Click Add user.
      • Type the username bob, set the Email Verified switch to ON, and click Save.
      • On the Credentials tab, set the password p. Enter the password in both the fields, set the Temporary switch to OFF to avoid the password reset at the next login, and click Set Password.

Now, let's run local cluster to test the kuadrantctl new command to generate authpolicy.

  • Clone the repo and checkout to the current PR branch authpolicy
  • Setup cluster, istio and Gateway API CRDs
make local-setup
  • Build and install CLI in bin/kuadrantctl path
make install
  • Install Kuadrant service protection. The CLI can be used to install kuadrant v0.4.1
bin/kuadrantctl install 
  • Deploy petstore backend API
kubectl create namespace petstore
kubectl apply -n petstore -f examples/petstore/petstore.yaml
  • Let's create Petstore's OpenAPI spec
cat <<EOF >petstore-openapi.yaml
---
openapi: "3.0.3"
info:
  title: "Pet Store API"
  version: "1.0.0"
  x-kuadrant:
    route:
      name: "petstore"
      namespace: "petstore"
      hostnames:
        - example.com
      parentRefs:
        - name: istio-ingressgateway
          namespace: istio-system
servers:
  - url: https://example.io/api/v1
paths:
  /cat:
    x-kuadrant:
      backendRefs:
        - name: petstore
          port: 80
          namespace: petstore
    get:  # public (not auth)
      operationId: "getCat"
      responses:
        405:
          description: "invalid input"
  /dog:
    x-kuadrant:
      backendRefs:
        - name: petstore
          port: 80
          namespace: petstore
    get:  # secured
      operationId: "getDog"
      security:
        - openIdConnect: []
      responses:
        405:
          description: "invalid input"
components:
  securitySchemes:
    openIdConnect:
      type: openIdConnect
      openIdConnectUrl: https://${KEYCLOAK_PUBLIC_DOMAIN}/auth/realms/petstore
EOF

Replace ${KEYCLOAK_PUBLIC_DOMAIN} with your SSO instance domain

Operation Applied config
GET /api/v1/cat public (not auth)
GET /api/v1/dog OIDC authenticatred
  • Create the HTTPRoute using the CLI
bin/kuadrantctl generate gatewayapi httproute --oas petstore-openapi.yaml | kubectl apply -n petstore -f -
  • Create Kuadrant's Auth Policy
bin/kuadrantctl generate kuadrant authpolicy --oas petstore-openapi.yaml | kubectl apply -n petstore -f -

Now, we are ready to test OpenAPI endpoints ❗

  • GET /api/v1/cat -> It's a public endpoint, hence should return 200 Ok
curl  -H "Host: example.com" -i "http://127.0.0.1:9080/api/v1/cat"
  • GET /api/v1/dog -> It's a secured endpoint, hence, without credentials, it should return 401
curl -H "Host: example.com" -i "http://127.0.0.1:9080/api/v1/dog"
HTTP/1.1 401 Unauthorized
www-authenticate: Bearer realm="getDog"
x-ext-auth-reason: credential not found
date: Tue, 28 Nov 2023 09:38:26 GMT
server: istio-envoy
content-length: 0
  • Get authentication token. This example is using Direct Access Grants oauth2 grant type (also known as Client Credentials grant type). When configuring the Keycloak (OIDC provider) client settings, we enabled Direct Access Grants to enable this procedure. We will be authenticating as bob user with p password. We previously created bob user in Keycloak in the petstore realm.
export ACCESS_TOKEN=$(curl -k -H "Content-Type: application/x-www-form-urlencoded" \
        -d 'grant_type=password' \
        -d 'client_id=petstore' \
        -d 'scope=openid' \
        -d 'username=bob' \
        -d 'password=p' "https://${KEYCLOAK_PUBLIC_DOMAIN}/auth/realms/petstore/protocol/openid-connect/token" | jq -r '.access_token')

Replace ${KEYCLOAK_PUBLIC_DOMAIN} with your SSO instance domain

With the access token in place, let's try to get those puppies

curl -H "Authorization: Bearer $ACCESS_TOKEN" -H 'Host: example.com' http://127.0.0.1:9080/api/v1/dog -i

should return 200 Ok

@eguzki eguzki changed the base branch from main to kuadrant-extensions-server-path November 16, 2023 14:38
name: "petstore"
namespace: "petstore"
hostnames:
- example.com
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not getting from servers?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it could be. But I can see it broken because some host rewrite happens for some reasons. It should default to servers and be overridden somehow IMO. I will implement reading from servers and override from hostnames if the field exists.

@eguzki eguzki force-pushed the kuadrant-extensions-server-path branch from 8186bce to 64db41b Compare November 22, 2023 10:40
Base automatically changed from kuadrant-extensions-server-path to httproute-kuadrant-extensions November 22, 2023 14:16
@codecov-commenter
Copy link

codecov-commenter commented Nov 27, 2023

Codecov Report

Attention: 66 lines in your changes are missing coverage. Please review.

Comparison is base (d3d31d0) 0.42% compared to head (fdb047b) 0.38%.

Files Patch % Lines
cmd/generate_kuadrant_authpolicy.go 0.00% 65 Missing ⚠️
cmd/generate_kuadrant.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                       Coverage Diff                        @@
##           httproute-kuadrant-extensions     #46      +/-   ##
================================================================
- Coverage                           0.42%   0.38%   -0.04%     
================================================================
  Files                                 15      16       +1     
  Lines                                708     774      +66     
================================================================
  Hits                                   3       3              
- Misses                               705     771      +66     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@eguzki eguzki marked this pull request as ready for review November 28, 2023 10:41
@eguzki eguzki requested a review from jasonmadigan November 28, 2023 10:41
@jasonmadigan
Copy link
Member

👀

@jasonmadigan
Copy link
Member

seeing a panic - wondered if it was the spec, or something environmental.

kuadrantctl generate kuadrant authpolicy --oas ./openapi.yaml
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x78 pc=0x1039eea74]

goroutine 1 [running]:
github.com/kuadrant/kuadrantctl/pkg/kuadrantapi.AuthPolicyAuthenticationSchemeFromOAS(0x140000be3f0)
	/Users/jmadigan/Work/kuadrantctl/pkg/kuadrantapi/authpolicy.go:136 +0x344
github.com/kuadrant/kuadrantctl/cmd.buildAuthPolicy(0x140000be3f0?)
	/Users/jmadigan/Work/kuadrantctl/cmd/generate_kuadrant_authpolicy.go:84 +0xa4
github.com/kuadrant/kuadrantctl/cmd.runGenerateKuadrantAuthPolicy(0x140002c3e00?, {0x103a257ca?, 0x4?, 0x103a257ce?})
	/Users/jmadigan/Work/kuadrantctl/cmd/generate_kuadrant_authpolicy.go:56 +0xf0
github.com/spf13/cobra.(*Command).execute(0x14000400f00, {0x14000310180, 0x2, 0x2})
	/Users/jmadigan/go/pkg/mod/github.com/spf13/[email protected]/command.go:940 +0x658
github.com/spf13/cobra.(*Command).ExecuteC(0x14000209800)
	/Users/jmadigan/go/pkg/mod/github.com/spf13/[email protected]/command.go:1068 +0x320
github.com/spf13/cobra.(*Command).Execute(0x140001be130?)
	/Users/jmadigan/go/pkg/mod/github.com/spf13/[email protected]/command.go:992 +0x1c
main.main()
	/Users/jmadigan/Work/kuadrantctl/main.go:27 +0x58

spec: https://gist.github.com/jasonmadigan/6e1eae05423d7012a26eb0cc6a751b22

@eguzki
Copy link
Collaborator Author

eguzki commented Nov 28, 2023

seeing a panic - wondered if it was the spec, or something environmental.

kuadrantctl generate kuadrant authpolicy --oas ./openapi.yaml
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x78 pc=0x1039eea74]

goroutine 1 [running]:
github.com/kuadrant/kuadrantctl/pkg/kuadrantapi.AuthPolicyAuthenticationSchemeFromOAS(0x140000be3f0)
	/Users/jmadigan/Work/kuadrantctl/pkg/kuadrantapi/authpolicy.go:136 +0x344
github.com/kuadrant/kuadrantctl/cmd.buildAuthPolicy(0x140000be3f0?)
	/Users/jmadigan/Work/kuadrantctl/cmd/generate_kuadrant_authpolicy.go:84 +0xa4
github.com/kuadrant/kuadrantctl/cmd.runGenerateKuadrantAuthPolicy(0x140002c3e00?, {0x103a257ca?, 0x4?, 0x103a257ce?})
	/Users/jmadigan/Work/kuadrantctl/cmd/generate_kuadrant_authpolicy.go:56 +0xf0
github.com/spf13/cobra.(*Command).execute(0x14000400f00, {0x14000310180, 0x2, 0x2})
	/Users/jmadigan/go/pkg/mod/github.com/spf13/[email protected]/command.go:940 +0x658
github.com/spf13/cobra.(*Command).ExecuteC(0x14000209800)
	/Users/jmadigan/go/pkg/mod/github.com/spf13/[email protected]/command.go:1068 +0x320
github.com/spf13/cobra.(*Command).Execute(0x140001be130?)
	/Users/jmadigan/go/pkg/mod/github.com/spf13/[email protected]/command.go:992 +0x1c
main.main()
	/Users/jmadigan/Work/kuadrantctl/main.go:27 +0x58

spec: https://gist.github.com/jasonmadigan/6e1eae05423d7012a26eb0cc6a751b22

Ok, sorry about that. I fixed it.

However, even if your OAS is syntactically correct, it does not specify what you aim to represent. The GET /api/v3//store/inventory is protected with the api_key security scheme, and not with the intended secureDog one. Kuadrant extensions x-kuadrant does not define security field. The tool reads security requriements from opeation's security field, not from the kuadrant extension security field.

Now, it should not panic, just return an authpolicy without rules.

@jasonmadigan
Copy link
Member

Ran through the comprehensive steps (thank you for including) and this worked good

@eguzki eguzki merged commit 1148fc8 into httproute-kuadrant-extensions Nov 28, 2023
5 checks passed
@eguzki eguzki deleted the authpolicy branch November 28, 2023 22:13
@eguzki eguzki mentioned this pull request Nov 29, 2023
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants