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

Refactor Auth server identity check. #12871

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@

import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.auth.serveridentity.ServerIdentity;
import com.alibaba.nacos.auth.serveridentity.ServerIdentityChecker;
import com.alibaba.nacos.auth.serveridentity.ServerIdentityCheckerHolder;
import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.auth.util.Loggers;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Permission;
import com.alibaba.nacos.plugin.auth.api.Resource;
Expand All @@ -42,8 +47,16 @@ public abstract class AbstractProtocolAuthService<R> implements ProtocolAuthServ

protected final AuthConfigs authConfigs;

protected final ServerIdentityChecker checker;

protected AbstractProtocolAuthService(AuthConfigs authConfigs) {
this.authConfigs = authConfigs;
this.checker = ServerIdentityCheckerHolder.getInstance().getChecker();
}

@Override
public void initialize() {
this.checker.init(authConfigs);
}

@Override
Expand Down Expand Up @@ -78,6 +91,30 @@ public boolean validateAuthority(IdentityContext identityContext, Permission per
return true;
}

@Override
public ServerIdentityResult checkServerIdentity(R request, Secured secured) {
if (isInvalidServerIdentity()) {
return ServerIdentityResult.fail(
"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`"
+ " and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`");
}
ServerIdentity serverIdentity = parseServerIdentity(request);
return checker.check(serverIdentity, secured);
}

private boolean isInvalidServerIdentity() {
return StringUtils.isBlank(authConfigs.getServerIdentityKey()) || StringUtils.isBlank(
authConfigs.getServerIdentityValue());
}

/**
* Parse server identity from protocol request.
*
* @param request protocol request
* @return nacos server identity.
*/
protected abstract ServerIdentity parseServerIdentity(R request);

/**
* Get resource from secured annotation specified resource.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.serveridentity.ServerIdentity;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Resource;
import com.alibaba.nacos.auth.config.AuthConfigs;
Expand Down Expand Up @@ -51,6 +52,7 @@ public GrpcProtocolAuthService(AuthConfigs authConfigs) {

@Override
public void initialize() {
super.initialize();
resourceParserMap.put(SignType.NAMING, new NamingGrpcResourceParser());
resourceParserMap.put(SignType.CONFIG, new ConfigGrpcResourceParser());
}
Expand All @@ -73,4 +75,11 @@ public Resource parseResource(Request request, Secured secured) {
public IdentityContext parseIdentity(Request request) {
return identityContextBuilder.build(request);
}

@Override
protected ServerIdentity parseServerIdentity(Request request) {
String serverIdentityKey = authConfigs.getServerIdentityKey();
String serverIdentity = request.getHeader(serverIdentityKey);
return new ServerIdentity(serverIdentityKey, serverIdentity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.alibaba.nacos.auth;

import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.serveridentity.ServerIdentity;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Resource;
import com.alibaba.nacos.auth.config.AuthConfigs;
Expand Down Expand Up @@ -51,6 +52,7 @@ public HttpProtocolAuthService(AuthConfigs authConfigs) {

@Override
public void initialize() {
super.initialize();
resourceParserMap.put(SignType.NAMING, new NamingHttpResourceParser());
resourceParserMap.put(SignType.CONFIG, new ConfigHttpResourceParser());
}
Expand All @@ -72,4 +74,11 @@ public Resource parseResource(HttpServletRequest request, Secured secured) {
public IdentityContext parseIdentity(HttpServletRequest request) {
return identityContextBuilder.build(request);
}

@Override
protected ServerIdentity parseServerIdentity(HttpServletRequest request) {
String serverIdentityKey = authConfigs.getServerIdentityKey();
String serverIdentity = request.getHeader(serverIdentityKey);
return new ServerIdentity(serverIdentityKey, serverIdentity);
}
}
10 changes: 10 additions & 0 deletions auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.alibaba.nacos.auth;

import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
import com.alibaba.nacos.plugin.auth.api.Permission;
import com.alibaba.nacos.plugin.auth.api.Resource;
Expand Down Expand Up @@ -85,4 +86,13 @@ public interface ProtocolAuthService<R> {
* @throws AccessException exception during validating
*/
boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException;

/**
* check server identity.
*
* @param request protocol request
* @param secured secured api secured annotation
* @return server identity result
*/
ServerIdentityResult checkServerIdentity(R request, Secured secured);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* 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.
*/

package com.alibaba.nacos.auth.serveridentity;

import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.config.AuthConfigs;

/**
* Nacos default server identity checker.
*
* @author xiweng.yy
*/
public class DefaultChecker implements ServerIdentityChecker {

private AuthConfigs authConfigs;

@Override
public void init(AuthConfigs authConfigs) {
this.authConfigs = authConfigs;
}

@Override
public ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured) {
if (authConfigs.getServerIdentityValue().equals(serverIdentity.getIdentityValue())) {
return ServerIdentityResult.success();
}
return ServerIdentityResult.noMatched();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* 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.
*/

package com.alibaba.nacos.auth.serveridentity;

/**
* Nacos server identity.
*
* @author xiweng.yy
*/
public class ServerIdentity {

private final String identityKey;

private final String identityValue;

public ServerIdentity(String identityKey, String identityValue) {
this.identityKey = identityKey;
this.identityValue = identityValue;
}

public String getIdentityKey() {
return identityKey;
}

public String getIdentityValue() {
return identityValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* 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.
*/

package com.alibaba.nacos.auth.serveridentity;

import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.config.AuthConfigs;

/**
* Nacos server identity checker for nacos inner/admin API identity check.
*
* @author xiweng.yy
*/
public interface ServerIdentityChecker {

/**
* Do init checker.
*
* @param authConfigs config for nacos auth.
*/
void init(AuthConfigs authConfigs);

/**
* Do check nacos server identity.
*
* @param serverIdentity server identity
* @param secured secured api secured annotation
* @return result of checking server identity
*/
ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* 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.
*/

package com.alibaba.nacos.auth.serveridentity;

import com.alibaba.nacos.common.spi.NacosServiceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;

/**
* Server Identity Checker SPI holder.
*
* @author xiweng.yy
*/
public class ServerIdentityCheckerHolder {

private static final Logger LOGGER = LoggerFactory.getLogger(ServerIdentityCheckerHolder.class);

private static final ServerIdentityCheckerHolder INSTANCE = new ServerIdentityCheckerHolder();

private ServerIdentityChecker checker;

private ServerIdentityCheckerHolder() {
tryGetCheckerBySpi();
}

public static ServerIdentityCheckerHolder getInstance() {
return INSTANCE;
}

public ServerIdentityChecker getChecker() {
return checker;
}

private synchronized void tryGetCheckerBySpi() {
Collection<ServerIdentityChecker> checkers = NacosServiceLoader.load(ServerIdentityChecker.class);
if (checkers.isEmpty()) {
checker = new DefaultChecker();
LOGGER.info("Not found ServerIdentityChecker implementation from SPI, use default.");
return;
}
if (checkers.size() > 1) {
checker = showAllImplementations(checkers);
return;
}
checker = checkers.iterator().next();
LOGGER.info("Found ServerIdentityChecker implementation {}", checker.getClass().getCanonicalName());
}

private ServerIdentityChecker showAllImplementations(Collection<ServerIdentityChecker> checkers) {
ServerIdentityChecker result = checkers.iterator().next();
for (ServerIdentityChecker each : checkers) {
LOGGER.warn("Found ServerIdentityChecker implementation {}", each.getClass().getCanonicalName());
}
LOGGER.warn("Found more than one ServerIdentityChecker implementation from SPI, use the first one {}.",
result.getClass().getCanonicalName());
return result;
}
}
Loading
Loading