1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.starter;
20
21 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
22 import io.swagger.v3.oas.integration.api.OpenAPIConfiguration;
23 import io.swagger.v3.oas.models.security.SecurityScheme;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.regex.Pattern;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.cxf.Bus;
30 import org.apache.cxf.endpoint.Server;
31 import org.apache.cxf.jaxrs.ext.MessageContext;
32 import org.apache.cxf.jaxrs.model.doc.JavaDocProvider;
33 import org.apache.cxf.jaxrs.openapi.OpenApiCustomizer;
34 import org.apache.cxf.jaxrs.openapi.OpenApiFeature;
35 import org.apache.cxf.jaxrs.spring.JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean;
36 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
37 import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
38 import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
39 import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
40 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
41 import org.apache.syncope.common.keymaster.client.api.DomainOps;
42 import org.apache.syncope.common.keymaster.client.api.DomainWatcher;
43 import org.apache.syncope.common.keymaster.client.api.KeymasterProperties;
44 import org.apache.syncope.common.keymaster.client.api.ServiceOps;
45 import org.apache.syncope.common.keymaster.rest.api.service.ConfParamService;
46 import org.apache.syncope.common.keymaster.rest.api.service.DomainService;
47 import org.apache.syncope.common.keymaster.rest.api.service.NetworkServiceService;
48 import org.apache.syncope.core.keymaster.internal.InternalConfParamHelper;
49 import org.apache.syncope.core.keymaster.internal.SelfKeymasterInternalConfParamOps;
50 import org.apache.syncope.core.keymaster.internal.SelfKeymasterInternalDomainOps;
51 import org.apache.syncope.core.keymaster.internal.SelfKeymasterInternalServiceOps;
52 import org.apache.syncope.core.keymaster.rest.cxf.service.ConfParamServiceImpl;
53 import org.apache.syncope.core.keymaster.rest.cxf.service.DomainServiceImpl;
54 import org.apache.syncope.core.keymaster.rest.cxf.service.NetworkServiceServiceImpl;
55 import org.apache.syncope.core.keymaster.rest.security.SelfKeymasterUsernamePasswordAuthenticationProvider;
56 import org.apache.syncope.core.logic.ConfParamLogic;
57 import org.apache.syncope.core.logic.DomainLogic;
58 import org.apache.syncope.core.logic.NetworkServiceLogic;
59 import org.apache.syncope.core.persistence.api.dao.ConfParamDAO;
60 import org.apache.syncope.core.persistence.api.dao.DomainDAO;
61 import org.apache.syncope.core.persistence.api.dao.NetworkServiceDAO;
62 import org.apache.syncope.core.persistence.api.entity.SelfKeymasterEntityFactory;
63 import org.apache.syncope.core.persistence.jpa.dao.JPAConfParamDAO;
64 import org.apache.syncope.core.persistence.jpa.dao.JPADomainDAO;
65 import org.apache.syncope.core.persistence.jpa.dao.JPANetworkServiceDAO;
66 import org.apache.syncope.core.persistence.jpa.entity.JPASelfKeymasterEntityFactory;
67 import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
68 import org.apache.syncope.core.rest.cxf.JavaDocUtils;
69 import org.apache.syncope.core.rest.cxf.RestServiceExceptionMapper;
70 import org.apache.syncope.core.spring.security.AuthDataAccessor;
71 import org.apache.syncope.core.spring.security.DefaultCredentialChecker;
72 import org.apache.syncope.core.spring.security.SecurityProperties;
73 import org.apache.syncope.core.spring.security.UsernamePasswordAuthenticationProvider;
74 import org.apache.syncope.core.spring.security.WebSecurityContext;
75 import org.apache.syncope.core.starter.SelfKeymasterContext.SelfKeymasterCondition;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
78 import org.springframework.boot.autoconfigure.AutoConfigureBefore;
79 import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
80 import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
81 import org.springframework.boot.context.properties.EnableConfigurationProperties;
82 import org.springframework.context.annotation.Bean;
83 import org.springframework.context.annotation.ConditionContext;
84 import org.springframework.context.annotation.Conditional;
85 import org.springframework.context.annotation.Configuration;
86 import org.springframework.core.env.Environment;
87 import org.springframework.core.type.AnnotatedTypeMetadata;
88
89 @EnableConfigurationProperties(KeymasterProperties.class)
90 @Configuration(proxyBeanMethods = false)
91 @AutoConfigureBefore(WebSecurityContext.class)
92 @Conditional(SelfKeymasterCondition.class)
93 public class SelfKeymasterContext {
94
95 private static final Logger LOG = LoggerFactory.getLogger(SelfKeymasterContext.class);
96
97 private static final Pattern HTTP = Pattern.compile("^http.+");
98
99 static class SelfKeymasterCondition extends SpringBootCondition {
100
101 @Override
102 public ConditionOutcome getMatchOutcome(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
103 String keymasterAddress = context.getEnvironment().getProperty("keymaster.address");
104 return new ConditionOutcome(
105 keymasterAddress != null && HTTP.matcher(keymasterAddress).matches(),
106 "Keymaster address not set for Self: " + keymasterAddress);
107 }
108 }
109
110 @Bean
111 public Server selfKeymasterContainer(
112 final ConfParamService confParamService,
113 final NetworkServiceService networkServiceService,
114 final DomainService domainService,
115 final JacksonJsonProvider jsonProvider,
116 final GZIPInInterceptor gzipInInterceptor,
117 final GZIPOutInterceptor gzipOutInterceptor,
118 final JAXRSBeanValidationInInterceptor validationInInterceptor,
119 final RestServiceExceptionMapper restServiceExceptionMapper,
120 final Bus bus,
121 final Environment env) {
122
123 SpringJAXRSServerFactoryBean selfKeymasterContainer = new SpringJAXRSServerFactoryBean();
124 selfKeymasterContainer.setBus(bus);
125 selfKeymasterContainer.setAddress("/keymaster");
126 selfKeymasterContainer.setStaticSubresourceResolution(true);
127
128 selfKeymasterContainer.setProperties(Map.of("convert.wadl.resources.to.dom", "false"));
129
130 selfKeymasterContainer.setServiceBeans(List.of(confParamService, networkServiceService, domainService));
131
132 selfKeymasterContainer.setInInterceptors(List.of(gzipInInterceptor, validationInInterceptor));
133
134 selfKeymasterContainer.setOutInterceptors(List.of(gzipOutInterceptor));
135
136 selfKeymasterContainer.setProviders(List.of(restServiceExceptionMapper, jsonProvider));
137
138
139 JavaDocProvider javaDocProvider = JavaDocUtils.getJavaDocURLs().
140 map(JavaDocProvider::new).
141 orElseGet(() -> JavaDocUtils.getJavaDocPaths(env).
142 map(javaDocPaths -> {
143 try {
144 return new JavaDocProvider(javaDocPaths);
145 } catch (Exception e) {
146 LOG.error("Could not set javadoc paths from {}", List.of(javaDocPaths), e);
147 return null;
148 }
149 }).
150 orElse(null));
151 OpenApiCustomizer openApiCustomizer = new OpenApiCustomizer() {
152
153 @Override
154 public OpenAPIConfiguration customize(final OpenAPIConfiguration configuration) {
155 super.customize(configuration);
156
157 MessageContext ctx = JAXRSUtils.createContextValue(
158 JAXRSUtils.getCurrentMessage(), null, MessageContext.class);
159
160 String url = StringUtils.substringBeforeLast(ctx.getUriInfo().getRequestUri().getRawPath(), "/");
161 configuration.getOpenAPI().setServers(List.of(new io.swagger.v3.oas.models.servers.Server().url(url)));
162
163 return configuration;
164 }
165 };
166 openApiCustomizer.setDynamicBasePath(false);
167 openApiCustomizer.setReplaceTags(false);
168 openApiCustomizer.setJavadocProvider(javaDocProvider);
169
170 String version = env.getProperty("version");
171 OpenApiFeature openapiFeature = new OpenApiFeature();
172 openapiFeature.setUseContextBasedConfig(true);
173 openapiFeature.setTitle("Apache Syncope Self Keymaster");
174 openapiFeature.setVersion(version);
175 openapiFeature.setDescription("Apache Syncope Self Keymaster" + version);
176 openapiFeature.setContactName("The Apache Syncope community");
177 openapiFeature.setContactEmail("dev@syncope.apache.org");
178 openapiFeature.setContactUrl("https://syncope.apache.org");
179 openapiFeature.setScan(false);
180 openapiFeature.setResourcePackages(Set.of("org.apache.syncope.common.keymaster.rest.api.service"));
181 openapiFeature.setSecurityDefinitions(
182 Map.of("BasicAuthentication", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")));
183 openapiFeature.setCustomizer(openApiCustomizer);
184 selfKeymasterContainer.setFeatures(List.of(openapiFeature));
185
186 return selfKeymasterContainer.create();
187 }
188
189 @Bean
190 public UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider(
191 final DomainOps domainOps,
192 final AuthDataAccessor dataAccessor,
193 final UserProvisioningManager provisioningManager,
194 final DefaultCredentialChecker credentialChecker,
195 final SecurityProperties securityProperties,
196 final KeymasterProperties keymasterProperties) {
197
198 return new SelfKeymasterUsernamePasswordAuthenticationProvider(
199 domainOps,
200 dataAccessor,
201 provisioningManager,
202 credentialChecker,
203 securityProperties,
204 keymasterProperties);
205 }
206
207 @Bean
208 public InternalConfParamHelper internalConfParamHelper(
209 final ConfParamDAO confParamDAO,
210 final SelfKeymasterEntityFactory entityFactory) {
211
212 return new InternalConfParamHelper(confParamDAO, entityFactory);
213 }
214
215 @Bean
216 public ConfParamOps internalConfParamOps(final InternalConfParamHelper helper) {
217 return new SelfKeymasterInternalConfParamOps(helper);
218 }
219
220 @Bean
221 public ServiceOps internalServiceOps(
222 final NetworkServiceLogic networkServiceLogic,
223 final KeymasterProperties props) {
224
225 return new SelfKeymasterInternalServiceOps(networkServiceLogic, props);
226 }
227
228 @Bean
229 public DomainOps domainOps(final DomainLogic domainLogic, final KeymasterProperties props) {
230 return new SelfKeymasterInternalDomainOps(domainLogic, props);
231 }
232
233 @Bean
234 public ConfParamLogic confParamLogic(final InternalConfParamHelper helper) {
235 return new ConfParamLogic(helper);
236 }
237
238 @Bean
239 public DomainLogic domainLogic(
240 final DomainDAO domainDAO,
241 final SelfKeymasterEntityFactory selfKeymasterEntityFactory,
242 final DomainWatcher domainWatcher) {
243
244 return new DomainLogic(domainDAO, selfKeymasterEntityFactory, domainWatcher);
245 }
246
247 @Bean
248 public NetworkServiceLogic networkServiceLogic(
249 final NetworkServiceDAO serviceDAO,
250 final SelfKeymasterEntityFactory selfKeymasterEntityFactory) {
251
252 return new NetworkServiceLogic(serviceDAO, selfKeymasterEntityFactory);
253 }
254
255 @Bean
256 public SelfKeymasterEntityFactory selfKeymasterEntityFactory() {
257 return new JPASelfKeymasterEntityFactory();
258 }
259
260 @Bean
261 public ConfParamDAO confParamDAO() {
262 return new JPAConfParamDAO();
263 }
264
265 @Bean
266 public DomainDAO domainDAO() {
267 return new JPADomainDAO();
268 }
269
270 @Bean
271 public NetworkServiceDAO networkServiceDAO() {
272 return new JPANetworkServiceDAO();
273 }
274
275 @Bean
276 public ConfParamService confParamService(final ConfParamLogic confParamLogic) {
277 return new ConfParamServiceImpl(confParamLogic);
278 }
279
280 @Bean
281 public DomainService domainService(final DomainLogic domainLogic) {
282 return new DomainServiceImpl(domainLogic);
283 }
284
285 @Bean
286 public NetworkServiceService networkServiceService(final NetworkServiceLogic networkServiceLogic) {
287 return new NetworkServiceServiceImpl(networkServiceLogic);
288 }
289 }