1 package cn.home1.cloud.config.server.environment;
2
3 import static com.google.common.collect.Sets.newLinkedHashSet;
4 import static org.apache.commons.lang3.StringUtils.isBlank;
5 import static org.apache.commons.lang3.StringUtils.isNotBlank;
6
7 import cn.home1.cloud.config.server.security.ConfigSecurity;
8 import cn.home1.cloud.config.server.util.EnvironmentUtils;
9
10 import lombok.Setter;
11 import lombok.extern.slf4j.Slf4j;
12
13 import org.springframework.boot.context.properties.ConfigurationProperties;
14 import org.springframework.cloud.config.environment.Environment;
15 import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository;
16 import org.springframework.core.env.ConfigurableEnvironment;
17 import org.springframework.security.authentication.BadCredentialsException;
18
19 import java.util.Set;
20
21 @ConfigurationProperties("spring.cloud.config.server.git")
22 @Slf4j
23 public class GitParentSupportMultipleJGitEnvironmentRepository extends MultipleJGitEnvironmentRepository {
24
25 @Setter
26 private ConfigSecurity configSecurity;
27
28 public GitParentSupportMultipleJGitEnvironmentRepository(final ConfigurableEnvironment environment) {
29 super(environment);
30 }
31
32 @Override
33 public Environment findOne(final String application, final String profile, final String label) {
34 final Environment currentApplicationEnv = super.findOne(application, profile, label);
35
36
37 final Set<String> history = newLinkedHashSet();
38 history.add(EnvironmentUtils.getApplicationName(currentApplicationEnv));
39
40 for (Environment parentEnv, applicationEnv = currentApplicationEnv;
41 (parentEnv = getParentEnvironment(applicationEnv, label)) != null;
42 applicationEnv = parentEnv) {
43
44 final String parentApplication = EnvironmentUtils.getParentApplication(applicationEnv);
45
46 final String expectedParentPassword = EnvironmentUtils.getConfigPassword(parentEnv);
47 if (isNotBlank(expectedParentPassword)) {
48 final String token = EnvironmentUtils.getParentConfigPassword(applicationEnv);
49 final Boolean hasParentPrivilege = this.configSecurity.verifyParentPassword(application, parentApplication, token, expectedParentPassword);
50 if (!hasParentPrivilege) {
51 throw new BadCredentialsException("Invalid access to parent config '" + parentApplication + "'.");
52 }
53 }
54
55 if (history.contains(parentApplication)) {
56 log.warn("circular reference detected! ignore existed parent. application:{}, circular parentApplication:{}",
57 application, parentApplication);
58 break;
59 } else {
60 history.add(parentApplication);
61 }
62
63
64
65 currentApplicationEnv.getPropertySources().addAll(parentEnv.getPropertySources());
66 }
67
68 return currentApplicationEnv;
69 }
70
71
72 private Environment getParentEnvironment(final Environment environment, final String label) {
73 final String parentApplication = EnvironmentUtils.getParentApplication(environment);
74 if (parentApplication == null || isBlank(parentApplication)) {
75 return null;
76 }
77 final String parentLabel = EnvironmentUtils.getParentLabel(environment, label);
78
79 Environment result = null;
80
81 String[] profiles = environment.getProfiles();
82 if (profiles == null || profiles.length == 0) {
83 profiles = new String[]{"default"};
84 }
85
86 for (final String profile : profiles) {
87 Environment found;
88 try {
89 found = super.findOne(parentApplication, profile, parentLabel);
90 } catch (final Exception exception) {
91 log.warn("error fetch parent exception! parentApplication:{}, profile:{}, parentLabel:{}",
92 parentApplication, profile, parentLabel, exception);
93 throw exception;
94 }
95
96 if (result == null) {
97 result = found;
98 } else {
99 result.getPropertySources().addAll(found.getPropertySources());
100 }
101 }
102 return result;
103 }
104 }