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

fixes #144 add product light-proxy-server configurations #145

Merged
merged 1 commit into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions product/light-proxy-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
The light proxy server configures the light gateway to bring a legacy API to the light ecosystem with all the cross-cutting concerns addressed on the same host.

### LPS configuration

For incoming requests, the light proxy server will execute a chain of middleware handlers before transferring the request to the backend API.

When the backend API calls another API, it calls the localhost light-proxy-server with a header of serviceId or service_id or service_url. This is the default configuration. You can also change the following properties in values.yml to all the light-proxy-server to differentiate ingress or egress traffic based on the protocol.

```
# sidecar.yml

sidecar.egressIngressIndicator: protocol
```

For incoming ingress requests from outside, use HTTPS; for outgoing egress requests from the backend API, use HTTP as it is localhost. So the LPC server starts with both HTTP 8080 and HTTPS 8443 ports.

We will use the default configuration header for the current demo configuration to indicate if the traffic is ingress or egress. As two ports are used, we can also use the protocol to differentiate the traffic.

The demo API is the market API, which will subsequently call the petstore API.

### Audience Validation

We use this config folder for the JWT audience validation test for the following three scenarios:

1. Single OAuth 2.0 provider

This is the default configuration for the light-proxy-server. The light proxy server will validate the audience against the audience in the JWT token. If the audience is not matched, the request will be rejected.

The values.yml file has a backup with the same content as the values-single.yml file.

2. Multiple OAuth 2.0 providers

3. Unified Security


105 changes: 105 additions & 0 deletions product/light-proxy-server/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016 Network New Technologies Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<configuration>
<!-- TODO create logger for audit only.
http://stackoverflow.com/questions/2488558/logback-to-log-different-messages-to-two-files -->
<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
<Marker>PROFILER</Marker>
<!--<OnMatch>DENY</OnMatch>-->
<OnMatch>NEUTRAL</OnMatch>
</turboFilter>

<!--stdout log-->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %X{sId} %X{cId} %-5level %class{36}:%L %M - %msg%n</pattern>
</encoder>
</appender>

<!--stdout-file log-->
<appender name="stdout-file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/stdout.log.json</file>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<fieldName>timestamp</fieldName>
<pattern>yyyy-MM-dd'T'HH:mm:ss.SSSZ</pattern>
</timestamp>
<pattern>
<pattern>
{
"thread": "%thread",
"level": "%-5level",
"logger": "%logger{64}",
"correlationId": "%X{cId}",
"serviceId": "%X{sId}",
"class": "%F",
"lineNumber": "%class{64}:%L",
"method": "%M",
"logMessage": "#tryJson{%message}"
}
</pattern>
</pattern>
<rootStackTraceElement/>
<stackTrace/>
</providers>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>log/stdout.log.json.%i.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>5</maxIndex> <!-- max number of archived logs that are kept -->
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>200MB
</maxFileSize> <!-- The size of the logfile that triggers a switch to a new logfile, and the current one archived -->
</triggeringPolicy>
</appender>

<!--audit log-->
<appender name="audit" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/schedular-audit.log.json</file> <!-- logfile location -->
<encoder>
<pattern>%msg%n</pattern> <!-- the layout pattern used to format log entries -->
<immediateFlush>true</immediateFlush>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>log/schedular-audit.log.json.%i.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>5</maxIndex> <!-- max number of archived logs that are kept -->
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>200MB
</maxFileSize> <!-- The size of the logfile that triggers a switch to a new logfile, and the current one archived -->
</triggeringPolicy>
</appender>

<root level="info">
<appender-ref ref="stdout"/>
</root>

<logger name="Audit" level="debug" additivity="false">
<appender-ref ref="audit"/>
</logger>

<logger name="com.networknt" level="trace" additivity="false">
<appender-ref ref="stdout"/>
</logger>

</configuration>
123 changes: 123 additions & 0 deletions product/light-proxy-server/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
openapi: "3.0.0"
info:
version: "1.0.0"
title: "Swagger Market"
license:
name: "MIT"
servers:
- url: "http://market.swagger.io"
paths:
/{store}/products:
get:
summary: "Get all products from stores"
operationId: "listProducts"
tags:
- "products"
parameters:
- name: "limit"
in: "query"
description: "How many items to return at one time (max 100)"
required: false
schema:
type: "integer"
format: "int32"
- name: "store"
in: "path"
description: "The downstream store name"
required: true
schema:
type: "string"
security:
- market_auth:
- "read:products"
responses:
"200":
description: "An paged array of products"
content:
application/json:
schema:
type: "array"
items:
$ref: "#/components/schemas/Product"
example:
- id: 1
name: "catten"
tag: "cat"
- id: 2
name: "doggy"
tag: "dog"
default:
description: "unexpected error"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: "Create a product"
operationId: "createProducts"
parameters:
- name: "store"
in: "path"
description: "The downstream store name"
required: true
schema:
type: "string"
requestBody:
description: "Product to add to the target store"
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/Product"
tags:
- "products"
security:
- market_auth:
- "read:products"
- "write:products"
responses:
"201":
description: "Null response"
default:
description: "unexpected error"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
securitySchemes:
market_auth:
type: "oauth2"
description: "This API uses OAuth 2 with the client credential grant flow."
flows:
clientCredentials:
tokenUrl: "https://localhost:6882/token"
scopes:
write:products: "modify products"
read:products: "read your products"
schemas:
Product:
type: "object"
required:
- "id"
- "name"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
tag:
type: "string"
Error:
type: "object"
required:
- "code"
- "message"
properties:
code:
type: "integer"
format: "int32"
message:
type: "string"
132 changes: 132 additions & 0 deletions product/light-proxy-server/values-multiple.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# This is a router configuration that can route traffic to multiple downstream APIs from a consumer.
# server.yml
server.enableHttp: true
server.serviceId: com.networknt.proxy-server

# client.yml
client.multipleAuthServers: true
client.pathPrefixServices:
/abc/products: com.networknt.market

client.tokenKeyServiceIdAuthServers:
com.networknt.market:
server_url: https://sunlifeapi.oktapreview.com
uri: /oauth2/aus66u5cybTrCsbZs1d6/v1/keys
enableHttp2: false
audience: dev.canada.referenceapi.sunlifeapis.oktapreview.com

client.tokenCcServiceIdAuthServers:
com.networknt.petstore:
server_url: https://sunlifeapi.oktapreview.com
uri: /oauth2/aus66u5cybTrCsbZs1d6/v1/token
enableHttp2: false
client_id: 0oa66u56irXiekQVQ1d6
client_secret: CR8h4P5Vbetwa-t8v5H6qhQ6jjQEv4dZJF2h50F3
scope:
- https://services.sunlife.com/okta/oauth2/corporate.reference-domain.petstore.pets.read

# proxy.yml
proxy.hosts: https://localhost:6443

# router.yml
router.maxRequestTime: 3000
router.hostWhitelist:
- localhost

# pathPrefixService.yml
pathPrefixService.mapping:
/v1/pets: com.networknt.petstore

# service.yml
service.singletons:
- com.networknt.registry.URL:
- com.networknt.registry.URLImpl
- com.networknt.registry.Registry:
- com.networknt.registry.support.DirectRegistry
- com.networknt.balance.LoadBalance:
- com.networknt.balance.RoundRobinLoadBalance
- com.networknt.cluster.Cluster:
- com.networknt.cluster.LightCluster

# direct-registry.yml
direct-registry.directUrls:
com.networknt.petstore: https://localhost:9443

# handler.yml
handler.enabled: true
handler.basePath: /
handler.handlers:
# Light-framework cross-cutting concerns implemented in the microservice
- com.networknt.exception.ExceptionHandler@exception
- com.networknt.metrics.MetricsHandler@metrics
- com.networknt.traceability.TraceabilityHandler@traceability
- com.networknt.correlation.CorrelationHandler@correlation
# Cors handler to handler post/put pre-flight. It is not used in the sidecar but only in the router.
- com.networknt.cors.CorsHttpHandler@cors
- com.networknt.openapi.OpenApiHandler@specification
- com.networknt.openapi.JwtVerifyHandler@security
- com.networknt.body.BodyHandler@body
- com.networknt.audit.AuditHandler@audit
- com.networknt.sanitizer.SanitizerHandler@sanitizer
- com.networknt.openapi.ValidatorHandler@validator
# Header middleware to manipulate request and/or response headers before or after downstream server
- com.networknt.header.HeaderHandler@header
# Rate limit middleware to prevent DDoS attacks externally or throttle requests internally
- com.networknt.limit.LimitHandler@limit
# IP whitelist handler to allow only one or several IPs to connect to the gateway.
# - com.networknt.whitelist.WhitelistHandler@whitelist
# Direct requests to named services based on the request path
- com.networknt.router.middleware.SidecarPathPrefixServiceHandler@prefix
- com.networknt.router.middleware.SidecarTokenHandler@token
- com.networknt.router.SidecarRouterHandler@router
- com.networknt.proxy.LightProxyHandler@proxy
- com.networknt.proxy.ProxyServerInfoHandler@proxyServerInfo
# - com.networknt.resource.VirtualHostHandler@virtual
# Customer business domain specific cross-cutting concerns handlers
# - com.example.validator.CustomizedValidator@custvalidator
# Framework endpoint handlers
# Control Pane middleware handlers and API handler
- com.networknt.chaos.KillappAssaultHandler@killapp
- com.networknt.chaos.LatencyAssaultHandler@latency
- com.networknt.chaos.MemoryAssaultHandler@memory
- com.networknt.chaos.ExceptionAssaultHandler@exchaos
- com.networknt.chaos.ChaosMonkeyGetHandler@chaosget
- com.networknt.chaos.ChaosMonkeyPostHandler@chaospost
- com.networknt.health.HealthGetHandler@health
- com.networknt.info.ServerInfoGetHandler@info
- com.networknt.logging.handler.LoggerGetHandler@getLogger
- com.networknt.logging.handler.LoggerPostHandler@postLogger
- com.networknt.logging.handler.LoggerGetLogContentsHandler@getLogContents
- com.networknt.config.reload.handler.ModuleRegistryGetHandler@modules
- com.networknt.config.reload.handler.ConfigReloadHandler@configReload
- com.networknt.specification.SpecDisplayHandler@spec
- com.networknt.specification.SpecSwaggerUIHandler@swaggerui
- com.networknt.specification.FaviconHandler@favicon
- com.networknt.router.OAuthServerHandler@oauth
- com.networknt.server.handler.ServerShutdownHandler@shutdown

handler.chains.default:
- exception
- prefix
# - metrics
- traceability
- correlation
# - cors
- header
#- audit
- token
- router
- specification
- security
- validator
#- sanitizer
- proxy

# openapi-security
openapi-security.enableVerifyScope: false
openapi-security.bootstrapFromKeyService: true

# token.yml
token.enabled: true
token.appliedPathPrefixes:
- /v1/pets
Loading