Skip to content

Commit

Permalink
fixes #2306 refactor security config to use only security.yml (#2307)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevehu authored Aug 6, 2024
1 parent 98d6dd0 commit 75555f7
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public class SecurityConfig {

private Map<String, String> passThroughClaims;

private SecurityConfig() {
this(CONFIG_NAME);
}

private SecurityConfig(String configName) {
config = Config.getInstance();
Expand All @@ -84,10 +87,29 @@ private SecurityConfig(String configName) {
setPassThroughClaims();
}

public static SecurityConfig load() {
return new SecurityConfig();
}

/**
* This method is only used in the test case to load different configuration files. Please use load() instead.
* @param configName String
* @return SecurityConfig
*/
@Deprecated
public static SecurityConfig load(String configName) {
return new SecurityConfig(configName);
}

public void reload() {
mappedConfig = config.getJsonMapConfigNoCache(CONFIG_NAME);
setCertificate();
setConfigData();
setSkipPathPrefixes();
setPassThroughClaims();
}

@Deprecated
public void reload(String configName) {
mappedConfig = config.getJsonMapConfigNoCache(configName);
setCertificate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,41 @@
# loaded for backward compatibility.
---
# Enable JWT verification flag.
enableVerifyJwt: ${openapi-security.enableVerifyJwt:false}
enableVerifyJwt: ${security.enableVerifyJwt:false}

# Enable JWT scope verification. Only valid when enableVerifyJwt is true.
enableVerifyScope: ${openapi-security.enableVerifyScope:true}
enableVerifyScope: ${security.enableVerifyScope:true}

# User for test only. should be always be false on official environment.
enableMockJwt: ${openapi-security.enableMockJwt:false}
enableMockJwt: ${security.enableMockJwt:false}

# JWT signature public certificates. kid and certificate path mappings.
jwt:
clockSkewInSeconds: 60

# Enable or disable JWT token logging
logJwtToken: ${openapi-security.logJwtToken:true}
logJwtToken: ${security.logJwtToken:true}

# Enable or disable client_id, user_id and scope logging.
logClientUserScope: ${openapi-security.logClientUserScope:false}
logClientUserScope: ${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}
enableJwtCache: ${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}
jwtCacheFullSize: ${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}
bootstrapFromKeyService: ${security.bootstrapFromKeyService:false}
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ skipPathPrefixes: ${security.skipPathPrefixes:}
# claim in the token and a header name that the downstream API is expecting. You can use
# both JSON or YAML format.
# YAML
# openapi-security.passThroughClaims:
# security.passThroughClaims:
# cid: client_id
# uid: user_id
# JSON
# openapi-security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
# security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
passThroughClaims: {"cid":"client_id","uid":"user_id"}
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ skipPathPrefixes: ${security.skipPathPrefixes:}
# claim in the token and a header name that the downstream API is expecting. You can use
# both JSON or YAML format.
# YAML
# openapi-security.passThroughClaims:
# security.passThroughClaims:
# cid: client_id
# uid: user_id
# JSON
# openapi-security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
# security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
passThroughClaims:
cid: client_id
uid: user_id
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,41 @@
# loaded for backward compatibility.
---
# Enable JWT verification flag.
enableVerifyJwt: ${openapi-security.enableVerifyJwt:false}
enableVerifyJwt: ${security.enableVerifyJwt:false}

# Enable JWT scope verification. Only valid when enableVerifyJwt is true.
enableVerifyScope: ${openapi-security.enableVerifyScope:true}
enableVerifyScope: ${security.enableVerifyScope:true}

# User for test only. should be always be false on official environment.
enableMockJwt: ${openapi-security.enableMockJwt:false}
enableMockJwt: ${security.enableMockJwt:false}

# JWT signature public certificates. kid and certificate path mappings.
jwt:
clockSkewInSeconds: 60

# Enable or disable JWT token logging
logJwtToken: ${openapi-security.logJwtToken:true}
logJwtToken: ${security.logJwtToken:true}

# Enable or disable client_id, user_id and scope logging.
logClientUserScope: ${openapi-security.logClientUserScope:false}
logClientUserScope: ${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}
enableJwtCache: ${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}
jwtCacheFullSize: ${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}
bootstrapFromKeyService: ${security.bootstrapFromKeyService:false}
4 changes: 2 additions & 2 deletions security/src/test/resources/config/security-json-claims.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ skipPathPrefixes: ${security.skipPathPrefixes:}
# claim in the token and a header name that the downstream API is expecting. You can use
# both JSON or YAML format.
# YAML
# openapi-security.passThroughClaims:
# security.passThroughClaims:
# cid: client_id
# uid: user_id
# JSON
# openapi-security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
# security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
passThroughClaims: {"cid":"client_id","uid":"user_id"}
4 changes: 2 additions & 2 deletions security/src/test/resources/config/security-yaml-claims.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ skipPathPrefixes: ${security.skipPathPrefixes:}
# claim in the token and a header name that the downstream API is expecting. You can use
# both JSON or YAML format.
# YAML
# openapi-security.passThroughClaims:
# security.passThroughClaims:
# cid: client_id
# uid: user_id
# JSON
# openapi-security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
# security.passThroughClaims: {"cid":"client_id","uid":"user_id"}
passThroughClaims:
cid: client_id
uid: user_id
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.networknt.security;

import com.networknt.config.Config;
import com.networknt.exception.ExpiredTokenException;
import com.networknt.handler.Handler;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.handler.config.HandlerConfig;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.httpstring.HttpStringConstants;
import com.networknt.utility.Constants;
import com.networknt.utility.ModuleRegistry;
import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
Expand All @@ -25,7 +22,6 @@

public abstract class AbstractJwtVerifyHandler extends UndertowVerifyHandler implements MiddlewareHandler, IJwtVerifyHandler {
static final Logger logger = LoggerFactory.getLogger(AbstractJwtVerifyHandler.class);
static final String OPENAPI_SECURITY_CONFIG = "openapi-security";
static final String STATUS_INVALID_AUTH_TOKEN = "ERR10000";
static final String STATUS_AUTH_TOKEN_EXPIRED = "ERR10001";
static final String STATUS_MISSING_AUTH_TOKEN = "ERR10002";
Expand All @@ -36,24 +32,12 @@ public abstract class AbstractJwtVerifyHandler extends UndertowVerifyHandler imp
static final String STATUS_INVALID_REQUEST_PATH = "ERR10007";
static final String STATUS_METHOD_NOT_ALLOWED = "ERR10008";

static SecurityConfig config;
public static SecurityConfig config;

// make this static variable public so that it can be accessed from the server-info module
public static JwtVerifier jwtVerifier;

String basePath;

private volatile HttpHandler next;

public AbstractJwtVerifyHandler() {
// at this moment, we assume that the OpenApiHandler is fully loaded with a single spec or multiple specs.
// And the basePath is the correct one from the OpenApiHandler helper or helperMap if multiple is used.
config = SecurityConfig.load(OPENAPI_SECURITY_CONFIG);
jwtVerifier = new JwtVerifier(config);
// in case that the specification doesn't exist, get the basePath from the handler.yml for endpoint lookup.
HandlerConfig handlerConfig = HandlerConfig.load();
this.basePath = handlerConfig == null ? "/" : handlerConfig.getBasePath();
}
public volatile HttpHandler next;

@Override
@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.networknt.security;

import com.networknt.config.Config;
import com.networknt.exception.ExpiredTokenException;
import com.networknt.handler.Handler;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.handler.config.HandlerConfig;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.httpstring.HttpStringConstants;
import com.networknt.utility.Constants;
import com.networknt.utility.ModuleRegistry;
import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
Expand All @@ -26,30 +23,17 @@

public abstract class AbstractSimpleJwtVerifyHandler extends UndertowVerifyHandler implements MiddlewareHandler, IJwtVerifyHandler {
static final Logger logger = LoggerFactory.getLogger(AbstractSimpleJwtVerifyHandler.class);
static final String SECURITY_CONFIG = "security";
static final String STATUS_INVALID_AUTH_TOKEN = "ERR10000";
static final String STATUS_AUTH_TOKEN_EXPIRED = "ERR10001";
static final String STATUS_MISSING_AUTH_TOKEN = "ERR10002";
static final String STATUS_METHOD_NOT_ALLOWED = "ERR10008";

static SecurityConfig config;
public static SecurityConfig config;

// make this static variable public so that it can be accessed from the server-info module
public static JwtVerifier jwtVerifier;

String basePath;

private volatile HttpHandler next;

public AbstractSimpleJwtVerifyHandler() {
// at this moment, we assume that the OpenApiHandler is fully loaded with a single spec or multiple specs.
// And the basePath is the correct one from the OpenApiHandler helper or helperMap if multiple is used.
config = SecurityConfig.load(SECURITY_CONFIG);
jwtVerifier = new JwtVerifier(config);
// in case that the specification doesn't exist, get the basePath from the handler.yml for endpoint lookup.
HandlerConfig handlerConfig = HandlerConfig.load();
this.basePath = handlerConfig == null ? "/" : handlerConfig.getBasePath();
}
public volatile HttpHandler next;

@Override
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -238,18 +222,6 @@ public boolean isEnabled() {
return config.isEnableVerifyJwt();
}

@Override
public void register() {
ModuleRegistry.registerModule(SECURITY_CONFIG, AbstractSimpleJwtVerifyHandler.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(SECURITY_CONFIG), null);
}

@Override
public void reload() {
config.reload(SECURITY_CONFIG);
jwtVerifier = new JwtVerifier(config);
ModuleRegistry.registerModule(SECURITY_CONFIG, AbstractSimpleJwtVerifyHandler.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(SECURITY_CONFIG), null);
}

@Override
public JwtVerifier getJwtVerifier() {
return jwtVerifier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

public abstract class AbstractSwtVerifyHandler extends UndertowVerifyHandler implements MiddlewareHandler {
static final Logger logger = LoggerFactory.getLogger(AbstractSwtVerifyHandler.class);
static final String OPENAPI_SECURITY_CONFIG = "openapi-security";
static final String STATUS_INVALID_AUTH_TOKEN = "ERR10000";
static final String STATUS_AUTH_TOKEN_EXPIRED = "ERR10001";
static final String STATUS_MISSING_AUTH_TOKEN = "ERR10002";
Expand All @@ -38,10 +37,8 @@ public abstract class AbstractSwtVerifyHandler extends UndertowVerifyHandler imp

public static SwtVerifier swtVerifier;

static SecurityConfig config;
private volatile HttpHandler next;

String basePath;
public static SecurityConfig config;
public volatile HttpHandler next;

@Override
public HttpHandler getNext() {
Expand Down Expand Up @@ -318,14 +315,4 @@ protected String getScopeToken(String authorization, HeaderMap headerMap) {
return returnToken;
}

public AbstractSwtVerifyHandler() {
// at this moment, we assume that the OpenApiHandler is fully loaded with a single spec or multiple specs.
// And the basePath is the correct one from the OpenApiHandler helper or helperMap if multiple is used.
config = SecurityConfig.load(OPENAPI_SECURITY_CONFIG);
swtVerifier = new SwtVerifier(config);
// in case that the specification doesn't exist, get the basePath from the handler.yml for endpoint lookup.
HandlerConfig handlerConfig = HandlerConfig.load();
this.basePath = handlerConfig == null ? "/" : handlerConfig.getBasePath();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
*/
public class UnifiedSecurityHandler implements MiddlewareHandler {
static final Logger logger = LoggerFactory.getLogger(UnifiedSecurityHandler.class);
static final String OPENAPI_SECURITY_CONFIG = "openapi-security";
static final String BEARER_PREFIX = "BEARER";
static final String BASIC_PREFIX = "BASIC";
static final String API_KEY = "apikey";
Expand All @@ -46,7 +45,7 @@ public class UnifiedSecurityHandler implements MiddlewareHandler {
public UnifiedSecurityHandler() {
logger.info("UnifiedSecurityHandler starts");
config = UnifiedSecurityConfig.load();
jwtVerifier = new JwtVerifier(SecurityConfig.load(OPENAPI_SECURITY_CONFIG));
jwtVerifier = new JwtVerifier(SecurityConfig.load());
}

@Override
Expand Down

0 comments on commit 75555f7

Please sign in to comment.