Skip to content

Commit 9d63411

Browse files
author
gitlab
committed
Merge branch 'fix-55369@@2' into 'master'
<feature>[crypto]: InfoSec MS envelope login See merge request zstackio/zstack!4068
2 parents d20e1ea + 9b9c526 commit 9d63411

File tree

31 files changed

+422
-118
lines changed

31 files changed

+422
-118
lines changed

conf/db/upgrade/V4.5.1.1__schema.sql

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE `zstack`.`InfoSecSecretResourcePoolVO` ADD COLUMN `encryptPublicKey` text DEFAULT NULL;
2+
ALTER TABLE `zstack`.`InfoSecSecretResourcePoolVO` ADD COLUMN `encryptSubjectDN` varchar(128) DEFAULT NULL;

conf/errorCodes/securityMachine.xml

+5
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,10 @@
3030
<id>3006</id>
3131
<description>The crypto service is not enabled</description>
3232
</code>
33+
34+
<code>
35+
<id>3007</id>
36+
<description>Operation not supported</description>
37+
</code>
3338
</error>
3439

conf/i18n/messages_en_US.properties

+14-2
Original file line numberDiff line numberDiff line change
@@ -9719,8 +9719,8 @@ certificate[uuid\=%s]\ not\ found = CCS certificate[uuid:{0}] does not exist
97199719
CCS\ certificate\ authentication\ disabled = CCS certificate authentication disabled. Please check whether the current secret resource pool is enabled
97209720

97219721
# at: src/test/crypto/org/zstack/crypto/ccs/CCSCertificateManagerImpl.java:230
9722-
# args: expectCryptoAuthenticationType, actualCryptoAuthenticationType
9723-
wrong\ crypto\ authentication\ type,\ expect[%s],\ actual[%s] = wrong crypto authentication type in UKey system tag, expect[{0}], actual[{1}]. Please check out your UKey system tag in API parameter
9722+
# args: expectCryptoAuthenticationId, actualCryptoAuthenticationId
9723+
wrong\ crypto\ authentication\ id,\ expect[%s],\ actual[%s] = wrong crypto authentication id in UKey system tag, expect[{0}], actual[{1}]. Please check out your UKey system tag in API parameter
97249724

97259725
# at: src/test/crypto/org/zstack/crypto/ccs/CCSCertificateManagerImpl.java:242
97269726
# args:
@@ -9749,3 +9749,15 @@ user[uuid\=%s]\ does\ not\ have\ any\ CCS\ certificate\ attached = user[uuid:{0}
97499749
# at: src/test/crypto/org/zstack/crypto/ccs/CCSCertificateInterceptor.java:172
97509750
# args: user.uuid, certificate.uuid
97519751
user[uuid\=%s]\ already\ has\ the\ certificate[uuid\=%s]\ attached = user[uuid:{0}] already has the certificate[uuid:{1}] attached
9752+
9753+
# at: src/main/java/org/zstack/encrypt/EncryptionParamApiInterceptor.java:77
9754+
# args: encryptionType
9755+
failed\ to\ parse\ API\ message\:\ can\ not\ parse\ encryption\ param\ with\ type\ %s = bad API request: invalid encryption mode {0}
9756+
9757+
# at: src/main/java/org/zstack/encrypt/EncryptionParamApiInterceptor.java:87
9758+
# args: encryptionType
9759+
failed\ to\ parse\ API\ message\:\ cipher\ text\ can\ not\ be\ parsed,\ type\=%s = bad API request: fail to parse encryption param by {0} encryption mode
9760+
9761+
# at: src/main/java/org/zstack/encrypt/EncryptionParamApiInterceptor.java:115
9762+
# args: count
9763+
failed\ to\ parse\ API\ message\:\ found\ %d\ encryption\ param\ system\ tags,\ expect\ 1 = bad API request: find {0} encryption param system tags, expect 1

conf/i18n/messages_zh_CN.properties

+14-2
Original file line numberDiff line numberDiff line change
@@ -9719,8 +9719,8 @@ certificate[uuid\=%s]\ not\ found = CCS证书[uuid:{0}]不存在
97199719
CCS\ certificate\ authentication\ disabled = CCS认证登录未启用。请检查当前是否启用密码机资源池
97209720

97219721
# at: src/test/crypto/org/zstack/crypto/ccs/CCSCertificateManagerImpl.java:230
9722-
# args: expectCryptoAuthenticationType, actualCryptoAuthenticationType
9723-
wrong\ crypto\ authentication\ type,\ expect[%s],\ actual[%s] = 输入参数UKey的System Tag中, 认证类型错误, 期望是[{0}], 但实际传入[{1}]
9722+
# args: expectCryptoAuthenticationId, actualCryptoAuthenticationId
9723+
wrong\ crypto\ authentication\ id,\ expect[%s],\ actual[%s] = 输入参数UKey的System Tag中, 认证类型错误, 期望是[{0}], 但实际传入[{1}]
97249724

97259725
# at: src/test/crypto/org/zstack/crypto/ccs/CCSCertificateManagerImpl.java:242
97269726
# args:
@@ -9749,3 +9749,15 @@ user[uuid\=%s]\ does\ not\ have\ any\ CCS\ certificate\ attached = = 用户[uuid
97499749
# at: src/test/crypto/org/zstack/crypto/ccs/CCSCertificateInterceptor.java:172
97509750
# args: certificate.uuid, user.uuid
97519751
user[uuid\=%s]\ already\ has\ the\ certificate[uuid\=%s]\ attached = 用户[uuid:{0}]已经绑定了CCS证书[uuid:{1}]
9752+
9753+
# at: src/main/java/org/zstack/encrypt/EncryptionParamApiInterceptor.java:77
9754+
# args: encryptionType
9755+
failed\ to\ parse\ API\ message\:\ can\ not\ parse\ encryption\ param\ with\ type\ %s = 错误的 API 输入: 无效的加密类型 {0}
9756+
9757+
# at: src/main/java/org/zstack/encrypt/EncryptionParamApiInterceptor.java:87
9758+
# args: encryptionType
9759+
failed\ to\ parse\ API\ message\:\ cipher\ text\ can\ not\ be\ parsed,\ type\=%s = 错误的 API 输入: 无法将参数密文以 {0} 加密类型解析
9760+
9761+
# at: src/main/java/org/zstack/encrypt/EncryptionParamApiInterceptor.java:115
9762+
# args: count
9763+
failed\ to\ parse\ API\ message\:\ found\ %d\ encryption\ param\ system\ tags,\ expect\ 1 = 错误的 API 输入: 发现 {0} 个加密参数 System Tags, 期望只传入一个

conf/springConfigXml/ApiMediator.xml

+6
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,10 @@
3636
<zstack:extension interface="org.zstack.header.message.ApiMessageValidator"/>
3737
</zstack:plugin>
3838
</bean>
39+
40+
<bean id="ApiParamValidator" class="org.zstack.portal.apimediator.ApiParamValidator">
41+
<zstack:plugin>
42+
<zstack:extension interface="org.zstack.header.apimediator.GlobalApiMessageInterceptor"/>
43+
</zstack:plugin>
44+
</bean>
3945
</beans>

conf/springConfigXml/Aspect.xml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<bean class="org.zstack.core.aspect.AsyncSafeAspect" factory-method="aspectOf" />
2020
<bean class="org.zstack.core.aspect.BackAspect" factory-method="aspectOf" />
2121
<bean class="org.zstack.core.aspect.EncryptColumnAspect" factory-method="aspectOf" />
22+
<bean class="org.zstack.core.aspect.ExceptionSafeAspect" factory-method="aspectOf" />
2223

2324
</beans>
2425

Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
11
package org.zstack.core.aspect;
22

3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.zstack.core.errorcode.ErrorFacade;
5+
import org.zstack.header.errorcode.ErrorableValue;
36
import org.zstack.utils.Utils;
47
import org.zstack.utils.logging.CLogger;
58

69
public aspect ExceptionSafeAspect {
710
private static final CLogger logger = Utils.getLogger(ExceptionSafeAspect.class);
811

9-
void around() : execution(@org.zstack.header.core.ExceptionSafe * *.*(..)) {
12+
@Autowired
13+
private ErrorFacade errf;
14+
15+
void around() : execution(@org.zstack.header.core.ExceptionSafe void *.*(..)) {
1016
try {
1117
proceed();
1218
} catch (Throwable t) {
1319
logger.warn("unhandled exception happened", t);
1420
}
1521
}
22+
23+
ErrorableValue around() : execution(@org.zstack.header.core.ExceptionSafe ErrorableValue *.*(..)) {
24+
try {
25+
return proceed();
26+
} catch (Throwable t) {
27+
return ErrorableValue.ofErrorCode(errf.throwableToInternalError(t));
28+
}
29+
}
1630
}

core/src/main/java/org/zstack/core/encrypt/DefaultEncryptDriver.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.zstack.core.encrypt;
22

33
import org.zstack.header.core.encrypt.EncryptConstant;
4+
import org.zstack.header.errorcode.ErrorableValue;
45
import org.zstack.header.exception.CloudRuntimeException;
56

67
public class DefaultEncryptDriver implements EncryptDriver {
@@ -32,18 +33,18 @@ public String decrypt(String data) {
3233
}
3334

3435
@Override
35-
public EncryptFacadeResult<String> encrypt(String data, String algType) {
36+
public ErrorableValue<String> encrypt(String data, String algType) {
3637
try {
37-
return new EncryptFacadeResult<>(rsa.encrypt(data, algType));
38+
return ErrorableValue.of(rsa.encrypt(data, algType));
3839
} catch (Exception e) {
3940
throw new CloudRuntimeException(e.getMessage());
4041
}
4142
}
4243

4344
@Override
44-
public EncryptFacadeResult<String> decrypt(String data, String algType) {
45+
public ErrorableValue<String> decrypt(String data, String algType) {
4546
try {
46-
return new EncryptFacadeResult<>(rsa.decrypt(data, algType));
47+
return ErrorableValue.of(rsa.decrypt(data, algType));
4748
} catch (Exception e) {
4849
throw new CloudRuntimeException(e.getMessage());
4950
}

core/src/main/java/org/zstack/core/encrypt/EncryptDriver.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.zstack.core.encrypt;
22

3+
import org.zstack.header.errorcode.ErrorableValue;
4+
35
public interface EncryptDriver {
46
String encryptError = "%s encrypt failed";
57
String decryptError = "%s decrypt failed";
@@ -10,7 +12,7 @@ public interface EncryptDriver {
1012

1113
String decrypt(String data);
1214

13-
EncryptFacadeResult<String> encrypt(String data, String algType);
15+
ErrorableValue<String> encrypt(String data, String algType);
1416

15-
EncryptFacadeResult<String> decrypt(String data, String algType);
17+
ErrorableValue<String> decrypt(String data, String algType);
1618
}

core/src/main/java/org/zstack/core/encrypt/EncryptFacade.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.zstack.header.core.encrypt.EncryptEntityState;
44
import org.zstack.header.core.encrypt.EncryptedFieldBundle;
5+
import org.zstack.header.errorcode.ErrorableValue;
56

67
import java.util.List;
78

@@ -13,9 +14,9 @@ public interface EncryptFacade {
1314

1415
String decrypt(String encryptString);
1516

16-
EncryptFacadeResult<String> encrypt(String data, String algType);
17+
ErrorableValue<String> encrypt(String data, String algType);
1718

18-
EncryptFacadeResult<String> decrypt(String data, String algType);
19+
ErrorableValue<String> decrypt(String data, String algType);
1920

2021
void updateEncryptDataStateIfExists(String entity, String column, EncryptEntityState state);
2122

core/src/main/java/org/zstack/core/encrypt/EncryptFacadeImpl.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.zstack.core.db.SQLBatch;
1414
import org.zstack.header.Component;
1515
import org.zstack.header.core.encrypt.*;
16+
import org.zstack.header.errorcode.ErrorableValue;
1617
import org.zstack.header.errorcode.OperationFailureException;
1718
import org.zstack.header.exception.CloudRuntimeException;
1819
import org.zstack.utils.BeanUtils;
@@ -64,12 +65,12 @@ public String decrypt(String encryptString) {
6465
}
6566

6667
@Override
67-
public EncryptFacadeResult<String> encrypt(String data, String algType) {
68+
public ErrorableValue<String> encrypt(String data, String algType) {
6869
return encryptDriver.encrypt(data, algType);
6970
}
7071

7172
@Override
72-
public EncryptFacadeResult<String> decrypt(String data, String algType) {
73+
public ErrorableValue<String> decrypt(String data, String algType) {
7374
return encryptDriver.decrypt(data, algType);
7475
}
7576

@@ -197,7 +198,7 @@ protected void scripts() {
197198

198199
try {
199200
String decryptedString = decrypt(encryptedString);
200-
EncryptFacadeResult<String> encrypt = encrypt(decryptedString, key);
201+
ErrorableValue<String> encrypt = encrypt(decryptedString, key);
201202
if (encrypt.error != null) {
202203
logger.error(String.format("Encryption error : %s", encrypt.error));
203204
throw new OperationFailureException(operr("Encryption error : %s", encrypt.error));
@@ -206,7 +207,7 @@ protected void scripts() {
206207
String sql = String.format("update %s set %s = :encrypted where uuid = :uuid", className, field.getName());
207208

208209
Query query = dbf.getEntityManager().createQuery(sql);
209-
query.setParameter("encrypted", encrypt.getResult());
210+
query.setParameter("encrypted", encrypt.result);
210211
query.setParameter("uuid", uuid);
211212
query.executeUpdate();
212213
} catch (Exception e) {

core/src/main/java/org/zstack/core/encrypt/EncryptFacadeResult.java

-38
This file was deleted.

header/src/main/java/org/zstack/header/apimediator/ApiMessageInterceptor.java

+4
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@
1010
*/
1111
public interface ApiMessageInterceptor {
1212
APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException;
13+
14+
default int getPriority() {
15+
return 0;
16+
}
1317
}

header/src/main/java/org/zstack/header/apimediator/GlobalApiMessageInterceptor.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44

55
public interface GlobalApiMessageInterceptor extends ApiMessageInterceptor {
66
enum InterceptorPosition {
7-
SYSTEM,
8-
FRONT,
9-
END,
7+
// In execution order
8+
SYSTEM, FRONT, DEFAULT, END
109
}
1110

1211
List<Class> getMessageClassToIntercept();
1312

14-
InterceptorPosition getPosition();
13+
/**
14+
* Sort by position, then {@link #getPriority()}
15+
*/
16+
default InterceptorPosition getPosition() {
17+
return InterceptorPosition.FRONT;
18+
}
1519
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.zstack.header.core.encrypt;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target({ElementType.TYPE})
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface EncryptionParamAllowed {
11+
/**
12+
* Encrypted fields are not allowed.
13+
*
14+
* By default, except for the userTags/systemTags fields,
15+
* all fields owned by {@link org.zstack.header.message.APIMessage} classes are not allowed
16+
*/
17+
String[] forbiddenFields() default {};
18+
19+
String ACTION_CHECK_USER_INFO = "checkUserInfo";
20+
String ACTION_PUT_USER_INFO_INTO_SYSTEM_TAG = "putUserInfoIntoSystemTag";
21+
22+
/**
23+
* Check the result of parsing from the digital envelope
24+
*
25+
* - (Default) {@link #ACTION_CHECK_USER_INFO}
26+
* checks whether the user tag in the digital envelope matches the user of the APIMessage session
27+
* Mismatch will throw an error
28+
* - {@link #ACTION_PUT_USER_INFO_INTO_SYSTEM_TAG}
29+
* system places the user data in the envelope in the system tag,
30+
* and this process will not generate errors and interrupts
31+
*
32+
* It is recommended to enable this option for all APIs
33+
* that support digital envelopes except login
34+
*/
35+
String[] actions() default { ACTION_CHECK_USER_INFO };
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.zstack.header.errorcode;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* Created by Wenhao.Zhang on 22/11/21
7+
*/
8+
public class ErrorableValue<T> {
9+
public final T result;
10+
public final ErrorCode error;
11+
12+
public static <T> ErrorableValue<T> of(T result) {
13+
return new ErrorableValue<>(result, null);
14+
}
15+
16+
public static <T> ErrorableValue<T> ofErrorCode(ErrorCode error) {
17+
return new ErrorableValue<>(null,
18+
Objects.requireNonNull(error, "errorCode in ErrorableValue can not be null"));
19+
}
20+
21+
protected ErrorableValue(T result, ErrorCode error) {
22+
this.result = result;
23+
this.error = error;
24+
}
25+
26+
public boolean isSuccess() {
27+
return error == null;
28+
}
29+
}

header/src/main/java/org/zstack/header/identity/APILogInByAccountMsg.java

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.apache.commons.lang.StringUtils;
44
import org.springframework.http.HttpMethod;
55
import org.zstack.header.identity.login.APICaptchaMessage;
6+
import org.zstack.header.core.encrypt.EncryptionParamAllowed;
67
import org.zstack.header.log.NoLogging;
78
import org.zstack.header.message.APIMessage;
89
import org.zstack.header.message.APIParam;
@@ -19,6 +20,7 @@
1920
method = HttpMethod.PUT,
2021
responseClass = APILogInReply.class
2122
)
23+
@EncryptionParamAllowed(actions = { EncryptionParamAllowed.ACTION_PUT_USER_INFO_INTO_SYSTEM_TAG })
2224
public class APILogInByAccountMsg extends APISessionMessage implements APILoginAuditor, APICaptchaMessage {
2325
@APIParam
2426
private String accountName;

header/src/main/java/org/zstack/header/identity/AccountConstant.java

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public interface AccountConstant {
2828
String PRINCIPAL_ACCOUNT = "account";
2929

3030
String LOGIN_TYPE = "account";
31+
String LOGIN_TYPE_AUTHENTICATIONS_KEY = "authentications";
3132

3233
String NO_EXIST_ACCOUNT ="no-exist-account:::%s";
3334

0 commit comments

Comments
 (0)