From 5b92909837c838b6f443cfa173187480a8289092 Mon Sep 17 00:00:00 2001 From: Steve Hu Date: Tue, 9 Apr 2024 16:50:41 -0400 Subject: [PATCH] fixes #364 Split unified-config for UnifiedSecurityHandle to share with Lambda native --- openapi-security/pom.xml | 4 + pom.xml | 11 + unified-config/pom.xml | 63 +++++ .../openapi/UnifiedPathPrefixAuth.java | 0 .../openapi/UnifiedSecurityConfig.java | 0 .../resources/config/openapi-security.yml | 123 +++++++++ .../resources/config/unified-security.yml | 31 +++ .../networknt/openapi/SecurityConfigTest.java | 0 .../openapi/UnifiedSecurityConfigTest.java | 0 .../test/resources/config/client.truststore | Bin 0 -> 885 bytes .../src/test/resources/config/handler.yml | 68 +++++ .../config/openapi-handler-multiple.yml | 9 + .../test/resources/config/openapi-market.yaml | 122 +++++++++ .../resources/config/openapi-petstore.yaml | 213 ++++++++++++++++ .../src/test/resources/config/openapi.yaml | 234 ++++++++++++++++++ .../config/unified-security-json.yml | 0 .../config/unified-security-nolist.yml | 0 .../resources/config/unified-security.yml | 26 ++ .../src/test/resources/config/values.yml | 55 ++++ .../src/test/resources/logback-test.xml | 75 ++++++ 20 files changed, 1034 insertions(+) create mode 100644 unified-config/pom.xml rename {openapi-security => unified-config}/src/main/java/com/networknt/openapi/UnifiedPathPrefixAuth.java (100%) rename {openapi-security => unified-config}/src/main/java/com/networknt/openapi/UnifiedSecurityConfig.java (100%) create mode 100644 unified-config/src/main/resources/config/openapi-security.yml create mode 100644 unified-config/src/main/resources/config/unified-security.yml rename {openapi-security => unified-config}/src/test/java/com/networknt/openapi/SecurityConfigTest.java (100%) rename {openapi-security => unified-config}/src/test/java/com/networknt/openapi/UnifiedSecurityConfigTest.java (100%) create mode 100644 unified-config/src/test/resources/config/client.truststore create mode 100644 unified-config/src/test/resources/config/handler.yml create mode 100644 unified-config/src/test/resources/config/openapi-handler-multiple.yml create mode 100644 unified-config/src/test/resources/config/openapi-market.yaml create mode 100644 unified-config/src/test/resources/config/openapi-petstore.yaml create mode 100644 unified-config/src/test/resources/config/openapi.yaml rename {openapi-security => unified-config}/src/test/resources/config/unified-security-json.yml (100%) rename {openapi-security => unified-config}/src/test/resources/config/unified-security-nolist.yml (100%) create mode 100644 unified-config/src/test/resources/config/unified-security.yml create mode 100644 unified-config/src/test/resources/config/values.yml create mode 100644 unified-config/src/test/resources/logback-test.xml diff --git a/openapi-security/pom.xml b/openapi-security/pom.xml index 7e539327..eafa2344 100644 --- a/openapi-security/pom.xml +++ b/openapi-security/pom.xml @@ -50,6 +50,10 @@ com.networknt security + + com.networknt + unified-config + com.networknt handler diff --git a/pom.xml b/pom.xml index 6462a8d6..05104afb 100644 --- a/pom.xml +++ b/pom.xml @@ -119,6 +119,7 @@ openapi-meta validator-config openapi-validator + unified-config openapi-security access-control specification @@ -147,6 +148,11 @@ openapi-validator ${project.version} + + com.networknt + unified-config + ${project.version} + com.networknt openapi-security @@ -178,6 +184,11 @@ http-string ${version.light-4j} + + com.networknt + security-config + ${version.light-4j} + com.networknt security diff --git a/unified-config/pom.xml b/unified-config/pom.xml new file mode 100644 index 00000000..6b2e7c30 --- /dev/null +++ b/unified-config/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + + + com.networknt + light-rest-4j + 2.1.34-SNAPSHOT + ../pom.xml + + + unified-config + jar + The unified-security config module shared with lambda-native. + + + + com.networknt + config + + + com.networknt + security-config + + + com.fasterxml.jackson.core + jackson-databind + + + org.slf4j + slf4j-api + + + + ch.qos.logback + logback-classic + test + + + junit + junit + test + + + + + diff --git a/openapi-security/src/main/java/com/networknt/openapi/UnifiedPathPrefixAuth.java b/unified-config/src/main/java/com/networknt/openapi/UnifiedPathPrefixAuth.java similarity index 100% rename from openapi-security/src/main/java/com/networknt/openapi/UnifiedPathPrefixAuth.java rename to unified-config/src/main/java/com/networknt/openapi/UnifiedPathPrefixAuth.java diff --git a/openapi-security/src/main/java/com/networknt/openapi/UnifiedSecurityConfig.java b/unified-config/src/main/java/com/networknt/openapi/UnifiedSecurityConfig.java similarity index 100% rename from openapi-security/src/main/java/com/networknt/openapi/UnifiedSecurityConfig.java rename to unified-config/src/main/java/com/networknt/openapi/UnifiedSecurityConfig.java diff --git a/unified-config/src/main/resources/config/openapi-security.yml b/unified-config/src/main/resources/config/openapi-security.yml new file mode 100644 index 00000000..98ab906b --- /dev/null +++ b/unified-config/src/main/resources/config/openapi-security.yml @@ -0,0 +1,123 @@ +# Security configuration for openapi-security in light-rest-4j. It is a specific config +# for OpenAPI framework security. It is introduced to support multiple frameworks in the +# same server instance. If this file cannot be found, the generic security.yml will be +# loaded for backward compatibility. +--- +# Enable the JWT verification flag. The JwtVerifierHandler will skip the JWT token verification +# if this flag is false. It should only be set to false on the dev environment for testing +# purposes. If you have some endpoints that want to skip the JWT verification, you can put the +# request path prefix in skipPathPrefixes. +enableVerifyJwt: ${openapi-security.enableVerifyJwt:true} + +# Enable the SWT verification flag. The SwtVerifierHandler will skip the SWT token verification +# if this flag is false. It should only be set to false on the dev environment for testing +# purposes. If you have some endpoints that want to skip the SWT verification, you can put the +# request path prefix in skipPathPrefixes. +enableVerifySwt: ${openapi-security.enableVerifySwt:false} + +# swt clientId header name. When light-gateway is used and the consumer app does not want to save +# the client secret in the configuration file, it can be passed in the header. +swtClientIdHeader: ${openapi-security.swtClientIdHeader:swt-client} +# swt clientSecret header name. When light-gateway is used and the consumer app does not want to save +# the client secret in the configuration file, it can be passed in the header. +swtClientSecretHeader: ${openapi-security.swtClientSecretHeader:swt-secret} + +# Extract JWT scope token from the X-Scope-Token header and validate the JWT token +enableExtractScopeToken: ${openapi-security.enableExtractScopeToken:true} + +# Enable JWT scope verification. This flag is valid when enableVerifyJwt is true. When using the +# light gateway as a centralized gateway without backend API specifications, you can still enable +# this flag to allow the admin endpoints to have scopes verified. And all backend APIs without +# specifications skip the scope verification if the spec does not exist with the skipVerifyScopeWithoutSpec +# flag to true. Also, you need to have the openapi.yml specification file in the config folder to +# enable it, as the scope verification compares the scope from the JWT token and the scope in the +# endpoint specification. +enableVerifyScope: ${openapi-security.enableVerifyScope:true} + +# Users should only use this flag in a shared light gateway if the backend API specifications are +# unavailable in the gateway config folder. If this flag is true and the enableVerifyScope is true, +# the security handler will invoke the scope verification for all endpoints. However, if the endpoint +# doesn't have a specification to retrieve the defined scopes, the handler will skip the scope verification. +skipVerifyScopeWithoutSpec: ${openapi-security.skipVerifyScopeWithoutSpec:false} + +# If set true, the JWT verifier handler will pass if the JWT token is expired already. Unless +# you have a strong reason, please use it only on the dev environment if your OAuth 2 provider +# doesn't support long-lived token for dev environment or test automation. +ignoreJwtExpiry: ${openapi-security.ignoreJwtExpiry:false} + +# set true if you want to allow http 1/1 connections to be upgraded to http/2 using the UPGRADE method (h2c). +# By default, this is set to false for security reasons. If you choose to enable it make sure you can handle http/2 w/o tls. +enableH2c: ${openapi-security.enableH2c:false} + +# User for test only. should be always be false on official environment. +enableMockJwt: ${openapi-security.enableMockJwt:false} + +# Enables relaxed verification for jwt. e.g. Disables key length requirements. +# Should be used in test environments only. +enableRelaxedKeyValidation: ${openapi-security.enableRelaxedKeyValidation:false} + +# JWT signature public certificates. kid and certificate path mappings. +jwt: + certificate: ${openapi-security.certificate:100=primary.crt&101=secondary.crt} +# '100': primary.crt +# '101': secondary.crt + clockSkewInSeconds: ${openapi-security.clockSkewInSeconds:60} + # Key distribution server standard: JsonWebKeySet for other OAuth 2.0 provider| X509Certificate for light-oauth2 + keyResolver: ${openapi-security.keyResolver:JsonWebKeySet} + +# Enable or disable JWT token logging for audit. This is to log the entire token +# or choose the next option that only logs client_id, user_id and scope. +logJwtToken: ${openapi-security.logJwtToken:true} + +# Enable or disable client_id, user_id and scope logging if you don't want to log +# the entire token. Choose this option or the option above. +logClientUserScope: ${openapi-security.logClientUserScope:false} + +# Enable JWT token cache to speed up verification. This will only verify expired time +# and skip the signature verification as it takes more CPU power and a long time. If +# each request has a different jwt token, like authorization code flow, this indicator +# should be turned off. Otherwise, the cached jwt will only be removed after 15 minutes +# and the cache can grow bigger if the number of requests is very high. This will cause +# memory kill in a Kubernetes pod if the memory setting is limited. +enableJwtCache: ${openapi-security.enableJwtCache:true} + +# If enableJwtCache is true, then an error message will be shown up in the log if the +# cache size is bigger than the jwtCacheFullSize. This helps the developers to detect +# cache problem if many distinct tokens flood the cache in a short period of time. If +# you see JWT cache exceeds the size limit in logs, you need to turn off the enableJwtCache +# or increase the cache full size to a bigger number from the default 100. +jwtCacheFullSize: ${openapi-security.jwtCacheFullSize:100} + +# If you are using light-oauth2, then you don't need to have oauth subfolder for public +# key certificate to verify JWT token, the key will be retrieved from key endpoint once +# the first token is arrived. Default to false for dev environment without oauth2 server +# or official environment that use other OAuth 2.0 providers. +bootstrapFromKeyService: ${openapi-security.bootstrapFromKeyService:false} + +# Used in light-oauth2 and oauth-kafka key service for federated deployment. Each instance +# will have a providerId, and it will be part of the kid to allow each instance to get the +# JWK from other instance based on the providerId in the kid. +providerId: ${openapi-security.providerId:} + +# Define a list of path prefixes to skip the security to ease the configuration for the +# handler.yml so that users can define some endpoint without security even through it uses +# the default chain. This is particularly useful in the light-gateway use case as the same +# instance might be shared with multiple consumers and providers with different security +# requirement. The format is a list of strings separated with commas or a JSON list in +# values.yml definition from config server, or you can use yaml format in this file. +skipPathPrefixes: ${openapi-security.skipPathPrefixes:} + +# When light-gateway or http-sidecar is used for security, sometimes, we need to pass some +# claims from the JWT or SWT to the backend API for further verification or audit. You can +# select some claims to pass to the backend API with HTTP headers. The format is a map of +# claim in the token and a header name that the downstream API is expecting. You can use +# both JSON or YAML format. +# When SwtVerifyHandler is used, the claim names are in https://github.com/networknt/light-4j/blob/master/client/src/main/java/com/networknt/client/oauth/TokenInfo.java +# When JwtVerifyHandler is used, the claim names is the JwtClaims claimName. +# YAML +# openapi-security.passThroughClaims: +# clientId: client_id +# tokenType: token_type +# JSON +# openapi-security.passThroughClaims: {"clientId":"client_id","tokenType":"token_type"} +passThroughClaims: ${openapi-security.passThroughClaims:} diff --git a/unified-config/src/main/resources/config/unified-security.yml b/unified-config/src/main/resources/config/unified-security.yml new file mode 100644 index 00000000..b513af97 --- /dev/null +++ b/unified-config/src/main/resources/config/unified-security.yml @@ -0,0 +1,31 @@ +# unified-security.yml +# indicate if this handler is enabled. By default, it will be enabled if it is injected into the +# request/response chain in the handler.yml configuration. +enabled: ${unified-security.enabled:true} +# Anonymous prefixes configuration. A list of request path prefixes. The anonymous prefixes will be checked +# first, and if any path is matched, all other security checks will be bypassed, and the request goes to +# the next handler in the chain. You can use json array or string separated by comma or YAML format. +anonymousPrefixes: ${unified-security.anonymousPrefixes:} +# String format with comma separator +# /v1/pets,/v1/cats,/v1/dogs +# JSON format as a string +# ["/v1/pets", "/v1/dogs", "/v1/cats"] +# YAML format +# - /v1/pets +# - /v1/dogs +# - /v1/cats +pathPrefixAuths: ${unified-security.pathPrefixAuths:} +# format as a string for config server. +# [{"prefix":"/salesforce","basic":true,"jwt":true,"apikey":true,"jwkServiceIds":"com.networknt.petstore-1.0.0, com.networknt.market-1.0.0"},{"prefix":"/blackrock","basic":true,"jwt":true,"jwkServiceIds":["com.networknt.petstore-1.0.0","com.networknt.market-1.0.0"]}] +# format with YAML for readability + # path prefix security configuration. + # - pathPrefix: /salesforce + # indicate if the basic auth is enabled for this path prefix + # basic: true + # indicate if the jwt token verification is enabled for this path prefix + # jwt: true + # indicate if the apikey is enabled for this path prefix + # apikey: true + # if jwt is true and there are two or more jwk servers for the path prefix, then list all the + # serviceIds for jwk in client.yml + # jwkServiceIds: service1,service2 diff --git a/openapi-security/src/test/java/com/networknt/openapi/SecurityConfigTest.java b/unified-config/src/test/java/com/networknt/openapi/SecurityConfigTest.java similarity index 100% rename from openapi-security/src/test/java/com/networknt/openapi/SecurityConfigTest.java rename to unified-config/src/test/java/com/networknt/openapi/SecurityConfigTest.java diff --git a/openapi-security/src/test/java/com/networknt/openapi/UnifiedSecurityConfigTest.java b/unified-config/src/test/java/com/networknt/openapi/UnifiedSecurityConfigTest.java similarity index 100% rename from openapi-security/src/test/java/com/networknt/openapi/UnifiedSecurityConfigTest.java rename to unified-config/src/test/java/com/networknt/openapi/UnifiedSecurityConfigTest.java diff --git a/unified-config/src/test/resources/config/client.truststore b/unified-config/src/test/resources/config/client.truststore new file mode 100644 index 0000000000000000000000000000000000000000..ded19d0cdfacba00842ff28296dd589e9889ef96 GIT binary patch literal 885 zcmezO_TO6u1_mY|W(3o0#i>PQsYO7pO|YeY8Ut&Do~eN)0|T>}K@+o)K@*eI0%j&g zCMK4EUu!cAc-c6$+C196^D;7WvoaV&8*&?PvN4CUun9A{I~npB@PIfR!mPn1i6yCq zyawDLKD#iBb7o1UA&&tUh|49+>|c}))5$H&NVixAi$xlwq$;dA*F_07I zH8eIbG_*7{F)}wbiW28F0&&fuT-sXR#HfVqSw>a{<|amd27@L>E~X|%MuuH!GGZ5| zbnd(UqEJttZEweoXhtddR*g09%T}b^EiIa}?{w6gT(GB$rz8$^t%Tu2pV@ zyF+C5a6jPLXnSdv-{pEv>%Zbt>Z~3XM=BS(|L_nh`!mHgfX|tI=Cx1Kh12?9G2Ys) z^lxH- zGTnS(UwI~``|6j^%b#9WnJc#Yg^FGH!s%w2`t$k4XS1rXOikBRstbD8*tbQzzVN-o zF*~ycC6x)U>J)y@dK$BLspt-N_S%;0+fNsSUG>U7wr1wlkOa-DKYN~aFE)|O@olbJ zx7C!1nUR4JIfQ`80T@Dz49V8%!N%6Fe!qDl_@2Rg()HXG{&`#Vr9!%-&d&+^DwSJf zaxG`>6SHPGb?I$(@A3adm(@HgrFb>n`Gcolxh%dox>ig5+GlZJ59Lew9Q+T$ze}7v zw@5)bYrE0hyVtL1$er9H;3)fdPWP$2MppKh+y{=`&zT?bevNL%q~nvP-r$v)B+@S| z?3KIyaHuSE_`QI$C1<4Wf1d6a%=#`Qa=*o+{67 + + + + TODO create logger for audit only. + http://stackoverflow.com/questions/2488558/logback-to-log-different-messages-to-two-files + + PROFILER + + NEUTRAL + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L %M - %msg%n + + + + + target/test.log + false + + %d{HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L %M - %msg%n + + + + + + target/audit.log + + %-5level [%thread] %date{ISO8601} %F:%L - %msg%n + true + + + target/audit.log.%i.zip + 1 + 5 + + + 200MB + + + + + + + +