From bbfc35681df40c635ba742fa9c413c9a5768f572 Mon Sep 17 00:00:00 2001 From: Gerard Snaauw Date: Thu, 13 Jun 2024 18:41:56 +0200 Subject: [PATCH 1/2] add separate endpoint for APISIX --- Dockerfile | 2 +- api/opa/api.go | 81 +++++++++++++++++++++++++++++++++++++++++++- api/opa/generated.go | 75 +++++++++++++++++++++++++++++++++++++++- api/pip/generated.go | 2 +- main.go | 2 +- makefile | 2 +- oas/opa.yaml | 29 +++++++++++++++- 7 files changed, 186 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 245d04b..d3532a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # golang alpine -FROM golang:1.22.3-alpine as builder +FROM golang:1.22.4-alpine as builder ARG TARGETARCH ARG TARGETOS diff --git a/api/opa/api.go b/api/opa/api.go index ed8dbdb..e2fa99b 100644 --- a/api/opa/api.go +++ b/api/opa/api.go @@ -2,9 +2,13 @@ package opa import ( "context" + "encoding/base64" + "encoding/json" + "errors" "fmt" - "github.com/nuts-foundation/nuts-pxp/policy" "strings" + + "github.com/nuts-foundation/nuts-pxp/policy" ) var _ StrictServerInterface = (*Wrapper)(nil) @@ -13,6 +17,81 @@ type Wrapper struct { DecisionMaker policy.DecisionMaker } +func (w Wrapper) EvaluateDocumentApisix(ctx context.Context, request EvaluateDocumentApisixRequestObject) (EvaluateDocumentApisixResponseObject, error) { + // APISIX combines the 'openid-connect' and 'opa' plugin results into the following body: + //{ + // "input": { + // "var": { + // "server_port": "9080", + // "remote_addr": "172.90.10.2", + // "timestamp": 1718289289, + // "remote_port": "54228", + // "server_addr": "172.90.10.12" + // }, + // "type": "http", + // "request": { + // "scheme": "http", + // "method": "POST", + // "host": "pep-right", + // "query": {}, + // "path": "/web/external/transfer/notify/21189b43-04d5-4f4f-86ed-e5ae21a87f84", + // "headers": { + // "X-Userinfo": "eyJvcmdhbml6YXRpb25fbmFtZSI6IkxlZnQiLCJzY29wZSI6ImVPdmVyZHJhY2h0LXJlY2VpdmVyIiwic3ViIjoiZGlkOndlYjpub2RlLnJpZ2h0LmxvY2FsOmlhbTpyaWdodCIsImV4cCI6MTcxODI5MDE4NiwiaWF0IjoxNzE4Mjg5Mjg2LCJpc3MiOiJkaWQ6d2ViOm5vZGUucmlnaHQubG9jYWw6aWFtOnJpZ2h0IiwiYWN0aXZlIjp0cnVlLCJjbGllbnRfaWQiOiJkaWQ6d2ViOm5vZGUubGVmdC5sb2NhbDppYW06bGVmdCIsIm9yZ2FuaXphdGlvbl9jaXR5IjoiR3JvZW5sbyJ9", + // "host": "pep-right:9080", + // "authorization": "Bearer TonUNXLwVn2UgJgVfpVDNa7WaXAlE2W-mS6CfqDzeP0", + // "content-length": "0", + // "user-agent": "go-resty/2.13.1 (https://github.com/go-resty/resty)", + // "X-Access-Token": "TonUNXLwVn2UgJgVfpVDNa7WaXAlE2W-mS6CfqDzeP0", + // "accept-encoding": "gzip", + // "content-type": "text/plain; charset=utf-8", + // "connection": "close" + // }, + // "port": 9080 + // } + // } + //} + + input, ok := (*request.Body)["input"].(map[string]interface{}) + if !ok { + return nil, errors.New("invalid request, missing 'input'") + } + httpRequest, ok := input["request"].(map[string]interface{}) + if !ok { + return nil, errors.New("invalid request, missing 'input.request'") + } + httpHeaders, ok := httpRequest["headers"].(map[string]interface{}) + if !ok { + return nil, errors.New("invalid request, missing 'input.request.headers'") + } + xUserinfoBase64, ok := httpHeaders["X-Userinfo"].(string) + if !ok { + return nil, errors.New("invalid request, missing 'input.request.headers.X-Userinfo is not a string'") + } + xUserinfoJSON, err := base64.URLEncoding.DecodeString(xUserinfoBase64) + if err != nil { + return nil, fmt.Errorf("invalid request, failed to base64 decode X-Userinfo: %w", err) + } + xUserinfo := map[string]interface{}{} + err = json.Unmarshal(xUserinfoJSON, &xUserinfo) + if err != nil { + return nil, fmt.Errorf("invalid request, failed to unmarshal X-Userinfo: %w", err) + } + + descision, err := w.DecisionMaker.Query(ctx, httpRequest, xUserinfo) + if err != nil { + return nil, err + } + + // Expected response by APISIX is of the form: + //{ + // "result": { + // "allow": true + // } + //} + result := map[string]interface{}{"allow": descision} + return EvaluateDocumentApisix200JSONResponse{Result: result}, nil +} + func (w Wrapper) EvaluateDocument(ctx context.Context, request EvaluateDocumentRequestObject) (EvaluateDocumentResponseObject, error) { // parse the requestLine and extract the method and path // the requestLine is formatted as an HTTP request line diff --git a/api/opa/generated.go b/api/opa/generated.go index 95d2a54..9c6f17c 100644 --- a/api/opa/generated.go +++ b/api/opa/generated.go @@ -1,6 +1,6 @@ // Package opa provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.1.0 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.3.0 DO NOT EDIT. package opa import ( @@ -14,6 +14,11 @@ import ( strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo" ) +// ApisixOutcome defines model for ApisixOutcome. +type ApisixOutcome struct { + Result map[string]interface{} `json:"result"` +} + // Outcome defines model for Outcome. type Outcome struct { // Allow The result of the OPA policy evaluation @@ -29,11 +34,20 @@ type EvaluateDocumentParams struct { XUserinfo map[string]interface{} `json:"X-Userinfo"` } +// EvaluateDocumentApisixJSONBody defines parameters for EvaluateDocumentApisix. +type EvaluateDocumentApisixJSONBody = map[string]interface{} + +// EvaluateDocumentApisixJSONRequestBody defines body for EvaluateDocumentApisix for application/json ContentType. +type EvaluateDocumentApisixJSONRequestBody = EvaluateDocumentApisixJSONBody + // ServerInterface represents all server handlers. type ServerInterface interface { // calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally // (POST /v1/data) EvaluateDocument(ctx echo.Context, params EvaluateDocumentParams) error + // calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally + // (POST /v1/data/apisix) + EvaluateDocumentApisix(ctx echo.Context) error } // ServerInterfaceWrapper converts echo contexts to parameters. @@ -89,6 +103,15 @@ func (w *ServerInterfaceWrapper) EvaluateDocument(ctx echo.Context) error { return err } +// EvaluateDocumentApisix converts echo context to params. +func (w *ServerInterfaceWrapper) EvaluateDocumentApisix(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.EvaluateDocumentApisix(ctx) + return err +} + // This is a simple interface which specifies echo.Route addition functions which // are present on both echo.Echo and echo.Group, since we want to allow using // either of them for path registration @@ -118,6 +141,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL } router.POST(baseURL+"/v1/data", wrapper.EvaluateDocument) + router.POST(baseURL+"/v1/data/apisix", wrapper.EvaluateDocumentApisix) } @@ -138,11 +162,31 @@ func (response EvaluateDocument200JSONResponse) VisitEvaluateDocumentResponse(w return json.NewEncoder(w).Encode(response) } +type EvaluateDocumentApisixRequestObject struct { + Body *EvaluateDocumentApisixJSONRequestBody +} + +type EvaluateDocumentApisixResponseObject interface { + VisitEvaluateDocumentApisixResponse(w http.ResponseWriter) error +} + +type EvaluateDocumentApisix200JSONResponse ApisixOutcome + +func (response EvaluateDocumentApisix200JSONResponse) VisitEvaluateDocumentApisixResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + // StrictServerInterface represents all server handlers. type StrictServerInterface interface { // calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally // (POST /v1/data) EvaluateDocument(ctx context.Context, request EvaluateDocumentRequestObject) (EvaluateDocumentResponseObject, error) + // calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally + // (POST /v1/data/apisix) + EvaluateDocumentApisix(ctx context.Context, request EvaluateDocumentApisixRequestObject) (EvaluateDocumentApisixResponseObject, error) } type StrictHandlerFunc = strictecho.StrictEchoHandlerFunc @@ -181,3 +225,32 @@ func (sh *strictHandler) EvaluateDocument(ctx echo.Context, params EvaluateDocum } return nil } + +// EvaluateDocumentApisix operation middleware +func (sh *strictHandler) EvaluateDocumentApisix(ctx echo.Context) error { + var request EvaluateDocumentApisixRequestObject + + var body EvaluateDocumentApisixJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.EvaluateDocumentApisix(ctx.Request().Context(), request.(EvaluateDocumentApisixRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "EvaluateDocumentApisix") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(EvaluateDocumentApisixResponseObject); ok { + return validResponse.VisitEvaluateDocumentApisixResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} diff --git a/api/pip/generated.go b/api/pip/generated.go index 0a83b3d..ad8ca73 100644 --- a/api/pip/generated.go +++ b/api/pip/generated.go @@ -1,6 +1,6 @@ // Package pip provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.1.0 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.3.0 DO NOT EDIT. package pip import ( diff --git a/main.go b/main.go index b4b0737..055a298 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,6 @@ import ( "context" "errors" "fmt" - "github.com/nuts-foundation/nuts-pxp/policy" "net/http" "os" "os/signal" @@ -35,6 +34,7 @@ import ( "github.com/nuts-foundation/nuts-pxp/api/pip" "github.com/nuts-foundation/nuts-pxp/config" "github.com/nuts-foundation/nuts-pxp/db" + "github.com/nuts-foundation/nuts-pxp/policy" ) func main() { diff --git a/makefile b/makefile index 2df9967..13622c2 100644 --- a/makefile +++ b/makefile @@ -3,7 +3,7 @@ run-generators: api install-tools: - go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@v2.1.0 + go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.3.0 go install go.uber.org/mock/mockgen@v0.4.0 go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2 diff --git a/oas/opa.yaml b/oas/opa.yaml index 0a68b69..0a70731 100644 --- a/oas/opa.yaml +++ b/oas/opa.yaml @@ -38,6 +38,26 @@ paths: application/json: schema: $ref: '#/components/schemas/Outcome' + /v1/data/apisix: + post: + operationId: evaluateDocumentApisix + summary: calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally + description: | + The given request and X-Userinfo headers are used to create the input document for the OPA policy. + tags: + - opa + requestBody: + content: + application/json: + schema: + type: object + responses: + '200': + description: Successful request. Returns the result of the OPA policy evaluation + content: + application/json: + schema: + $ref: '#/components/schemas/ApisixOutcome' components: schemas: Outcome: @@ -48,4 +68,11 @@ components: allow: type: boolean description: The result of the OPA policy evaluation - example: true \ No newline at end of file + example: true + ApisixOutcome: + type: object + required: + - result + properties: + result: + type: object \ No newline at end of file From 26885a9c4f3fe1c64e5801e1c8fa4e8eb66e1699 Mon Sep 17 00:00:00 2001 From: Gerard Snaauw Date: Tue, 16 Jul 2024 18:27:02 +0200 Subject: [PATCH 2/2] move data from headers to body --- Dockerfile | 6 ++-- api/opa/api.go | 81 +++++++++++++++++++------------------------ api/opa/generated.go | 82 ++++++++++---------------------------------- oas/opa.yaml | 60 +++++++++++++++++--------------- 4 files changed, 90 insertions(+), 139 deletions(-) diff --git a/Dockerfile b/Dockerfile index d3532a7..4bcd993 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # golang alpine -FROM golang:1.22.4-alpine as builder +FROM golang:1.22.5-alpine AS builder ARG TARGETARCH ARG TARGETOS @@ -12,8 +12,8 @@ RUN apk update \ musl-dev \ && update-ca-certificates -ENV GO111MODULE on -ENV GOPATH / +ENV GO111MODULE=on +ENV GOPATH=/ RUN mkdir /opt/nuts-pxp && cd /opt/nuts-pxp COPY go.mod . diff --git a/api/opa/api.go b/api/opa/api.go index e2fa99b..88fc7ed 100644 --- a/api/opa/api.go +++ b/api/opa/api.go @@ -6,8 +6,6 @@ import ( "encoding/json" "errors" "fmt" - "strings" - "github.com/nuts-foundation/nuts-pxp/policy" ) @@ -18,6 +16,9 @@ type Wrapper struct { } func (w Wrapper) EvaluateDocumentApisix(ctx context.Context, request EvaluateDocumentApisixRequestObject) (EvaluateDocumentApisixResponseObject, error) { + if request.Body == nil { + return nil, errors.New("missing body") + } // APISIX combines the 'openid-connect' and 'opa' plugin results into the following body: //{ // "input": { @@ -50,15 +51,41 @@ func (w Wrapper) EvaluateDocumentApisix(ctx context.Context, request EvaluateDoc // } // } //} + outcome, err := w.handleEvaluate(ctx, *request.Body) + if err != nil { + return nil, err + } - input, ok := (*request.Body)["input"].(map[string]interface{}) - if !ok { - return nil, errors.New("invalid request, missing 'input'") + // Expected response by APISIX is of the form: + //{ + // "result": { + // "allow": true + // } + //} + return EvaluateDocumentApisix200JSONResponse(*outcome), nil +} + +func (w Wrapper) EvaluateDocument(ctx context.Context, request EvaluateDocumentRequestObject) (EvaluateDocumentResponseObject, error) { + if request.Body == nil { + return nil, errors.New("missing body") } - httpRequest, ok := input["request"].(map[string]interface{}) + //fmt.Printf("%v\n", *request.Body) + + outcome, err := w.handleEvaluate(ctx, *request.Body) + if err != nil { + return nil, err + } + + return EvaluateDocument200JSONResponse(*outcome), nil +} + +func (w Wrapper) handleEvaluate(ctx context.Context, input Input) (*Outcome, error) { + + httpRequest, ok := input.Input["request"].(map[string]interface{}) if !ok { return nil, errors.New("invalid request, missing 'input.request'") } + httpHeaders, ok := httpRequest["headers"].(map[string]interface{}) if !ok { return nil, errors.New("invalid request, missing 'input.request.headers'") @@ -77,47 +104,9 @@ func (w Wrapper) EvaluateDocumentApisix(ctx context.Context, request EvaluateDoc return nil, fmt.Errorf("invalid request, failed to unmarshal X-Userinfo: %w", err) } - descision, err := w.DecisionMaker.Query(ctx, httpRequest, xUserinfo) - if err != nil { - return nil, err - } - - // Expected response by APISIX is of the form: - //{ - // "result": { - // "allow": true - // } - //} - result := map[string]interface{}{"allow": descision} - return EvaluateDocumentApisix200JSONResponse{Result: result}, nil -} - -func (w Wrapper) EvaluateDocument(ctx context.Context, request EvaluateDocumentRequestObject) (EvaluateDocumentResponseObject, error) { - // parse the requestLine and extract the method and path - // the requestLine is formatted as an HTTP request line - // e.g. "GET /api/v1/resource HTTP/1.1" - // we are only interested in the method and path - method, path, err := parseRequestLine(request.Params.Request) - if err != nil { - return nil, err - } - httpRequest := map[string]interface{}{} - httpRequest["method"] = method - httpRequest["path"] = path - - descision, err := w.DecisionMaker.Query(ctx, httpRequest, request.Params.XUserinfo) + decision, err := w.DecisionMaker.Query(ctx, httpRequest, xUserinfo) if err != nil { return nil, err } - return EvaluateDocument200JSONResponse{Allow: descision}, nil -} - -// parseRequestLine parses the request line and extracts the method and path -// e.g. "GET /api/v1/resource HTTP/1.1" -> "GET", "/api/v1/resource" -func parseRequestLine(requestLine string) (method, path string, err error) { - parts := strings.Split(requestLine, " ") - if len(parts) != 3 { - return "", "", fmt.Errorf("invalid request line: %s", requestLine) - } - return parts[0], parts[1], nil + return &Outcome{Result: map[string]interface{}{"allow": decision}}, nil } diff --git a/api/opa/generated.go b/api/opa/generated.go index 9c6f17c..60a7343 100644 --- a/api/opa/generated.go +++ b/api/opa/generated.go @@ -10,41 +10,32 @@ import ( "net/http" "github.com/labstack/echo/v4" - "github.com/oapi-codegen/runtime" strictecho "github.com/oapi-codegen/runtime/strictmiddleware/echo" ) -// ApisixOutcome defines model for ApisixOutcome. -type ApisixOutcome struct { - Result map[string]interface{} `json:"result"` +// Input defines model for Input. +type Input struct { + // Input Policy decision information. Must contain the fields in the example. + Input map[string]interface{} `json:"input"` } // Outcome defines model for Outcome. type Outcome struct { - // Allow The result of the OPA policy evaluation - Allow bool `json:"allow"` -} - -// EvaluateDocumentParams defines parameters for EvaluateDocument. -type EvaluateDocumentParams struct { - // Request request line from nginx - Request string `json:"request"` - - // XUserinfo token introspection result - XUserinfo map[string]interface{} `json:"X-Userinfo"` + // Result The result of the OPA policy evaluation + Result map[string]interface{} `json:"result"` } -// EvaluateDocumentApisixJSONBody defines parameters for EvaluateDocumentApisix. -type EvaluateDocumentApisixJSONBody = map[string]interface{} +// EvaluateDocumentJSONRequestBody defines body for EvaluateDocument for application/json ContentType. +type EvaluateDocumentJSONRequestBody = Input // EvaluateDocumentApisixJSONRequestBody defines body for EvaluateDocumentApisix for application/json ContentType. -type EvaluateDocumentApisixJSONRequestBody = EvaluateDocumentApisixJSONBody +type EvaluateDocumentApisixJSONRequestBody = Input // ServerInterface represents all server handlers. type ServerInterface interface { // calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally // (POST /v1/data) - EvaluateDocument(ctx echo.Context, params EvaluateDocumentParams) error + EvaluateDocument(ctx echo.Context) error // calls https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input internally // (POST /v1/data/apisix) EvaluateDocumentApisix(ctx echo.Context) error @@ -59,47 +50,8 @@ type ServerInterfaceWrapper struct { func (w *ServerInterfaceWrapper) EvaluateDocument(ctx echo.Context) error { var err error - // Parameter object where we will unmarshal all parameters from the context - var params EvaluateDocumentParams - - headers := ctx.Request().Header - // ------------- Required header parameter "request" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("request")]; found { - var Request string - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for request, got %d", n)) - } - - err = runtime.BindStyledParameterWithOptions("simple", "request", valueList[0], &Request, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true}) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter request: %s", err)) - } - - params.Request = Request - } else { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter request is required, but not found")) - } - // ------------- Required header parameter "X-Userinfo" ------------- - if valueList, found := headers[http.CanonicalHeaderKey("X-Userinfo")]; found { - var XUserinfo map[string]interface{} - n := len(valueList) - if n != 1 { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Userinfo, got %d", n)) - } - - err = json.Unmarshal([]byte(valueList[0]), &XUserinfo) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter 'X-Userinfo' as JSON") - } - - params.XUserinfo = XUserinfo - } else { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter X-Userinfo is required, but not found")) - } - // Invoke the callback with all the unmarshaled arguments - err = w.Handler.EvaluateDocument(ctx, params) + err = w.Handler.EvaluateDocument(ctx) return err } @@ -146,7 +98,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL } type EvaluateDocumentRequestObject struct { - Params EvaluateDocumentParams + Body *EvaluateDocumentJSONRequestBody } type EvaluateDocumentResponseObject interface { @@ -170,7 +122,7 @@ type EvaluateDocumentApisixResponseObject interface { VisitEvaluateDocumentApisixResponse(w http.ResponseWriter) error } -type EvaluateDocumentApisix200JSONResponse ApisixOutcome +type EvaluateDocumentApisix200JSONResponse Outcome func (response EvaluateDocumentApisix200JSONResponse) VisitEvaluateDocumentApisixResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/json") @@ -202,10 +154,14 @@ type strictHandler struct { } // EvaluateDocument operation middleware -func (sh *strictHandler) EvaluateDocument(ctx echo.Context, params EvaluateDocumentParams) error { +func (sh *strictHandler) EvaluateDocument(ctx echo.Context) error { var request EvaluateDocumentRequestObject - request.Params = params + var body EvaluateDocumentJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.EvaluateDocument(ctx.Request().Context(), request.(EvaluateDocumentRequestObject)) diff --git a/oas/opa.yaml b/oas/opa.yaml index 0a70731..29e162e 100644 --- a/oas/opa.yaml +++ b/oas/opa.yaml @@ -14,23 +14,11 @@ paths: The given request and X-Userinfo headers are used to create the input document for the OPA policy. tags: - opa - parameters: - - name: request - in: header - required: true - description: request line from nginx - schema: - type: string - example: GET /fhir/Patient/123?subject.identifier=1234567890 HTTP/1.1 - - name: X-Userinfo - in: header - required: true - description: token introspection result - content: - application/json: - schema: - type: object - example: {"client_id":"did:web:example.com:iam:client","sub":"did:web:example.com:iam:verifier", "scope":"eOverdracht-sender"} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Input' responses: '200': description: Successful request. Returns the result of the OPA policy evaluation @@ -50,29 +38,47 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/Input' responses: '200': description: Successful request. Returns the result of the OPA policy evaluation content: application/json: schema: - $ref: '#/components/schemas/ApisixOutcome' + $ref: '#/components/schemas/Outcome' components: schemas: - Outcome: + Input: type: object required: - - allow + - input properties: - allow: - type: boolean - description: The result of the OPA policy evaluation - example: true - ApisixOutcome: + input: + type: object + description: Policy decision information. Must contain the fields in the example. + example: | + { + "input": { + "request": { + "method": "GET", + "path": "/resource", + "headers": { + "X-Userinfo": "base64 encoded user info" + } + } + } + } + Outcome: type: object required: - result properties: result: - type: object \ No newline at end of file + type: object + description: The result of the OPA policy evaluation + example: | + { + "result": { + "allow": true + } + } \ No newline at end of file