1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.logic.wa;
20
21 import java.lang.reflect.Method;
22 import java.net.URI;
23 import java.net.http.HttpClient;
24 import java.net.http.HttpRequest;
25 import java.net.http.HttpResponse;
26 import java.util.List;
27 import java.util.Optional;
28 import java.util.stream.Collectors;
29 import javax.ws.rs.core.HttpHeaders;
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.cxf.transport.http.auth.DefaultBasicAuthSupplier;
32 import org.apache.syncope.common.keymaster.client.api.KeymasterException;
33 import org.apache.syncope.common.keymaster.client.api.ServiceOps;
34 import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
35 import org.apache.syncope.common.lib.Attr;
36 import org.apache.syncope.common.lib.to.EntityTO;
37 import org.apache.syncope.common.lib.types.AMEntitlement;
38 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
39 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
40 import org.apache.syncope.core.logic.AbstractTransactionalLogic;
41 import org.apache.syncope.core.logic.UnresolvedReferenceException;
42 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
43 import org.apache.syncope.core.persistence.api.dao.WAConfigDAO;
44 import org.apache.syncope.core.provisioning.api.data.WAConfigDataBinder;
45 import org.apache.syncope.core.spring.security.SecurityProperties;
46 import org.springframework.security.access.prepost.PreAuthorize;
47 import org.springframework.transaction.annotation.Transactional;
48 import org.springframework.util.CollectionUtils;
49
50 public class WAConfigLogic extends AbstractTransactionalLogic<EntityTO> {
51
52 protected final ServiceOps serviceOps;
53
54 protected final WAConfigDataBinder binder;
55
56 protected final WAConfigDAO waConfigDAO;
57
58 protected final SecurityProperties securityProperties;
59
60 public WAConfigLogic(
61 final ServiceOps serviceOps,
62 final WAConfigDataBinder binder,
63 final WAConfigDAO waConfigDAO,
64 final SecurityProperties securityProperties) {
65
66 this.serviceOps = serviceOps;
67 this.binder = binder;
68 this.waConfigDAO = waConfigDAO;
69 this.securityProperties = securityProperties;
70 }
71
72 @PreAuthorize("hasRole('" + AMEntitlement.WA_CONFIG_LIST + "') or hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
73 @Transactional(readOnly = true)
74 public List<Attr> list() {
75 return waConfigDAO.findAll().stream().map(binder::get).collect(Collectors.toList());
76 }
77
78 @PreAuthorize("hasRole('" + AMEntitlement.WA_CONFIG_GET + "')")
79 @Transactional(readOnly = true)
80 public Attr get(final String schema) {
81 return Optional.ofNullable(waConfigDAO.find(schema)).
82 map(binder::get).
83 orElseThrow(() -> new NotFoundException("Configuration entry " + schema + " not found"));
84 }
85
86 @PreAuthorize("hasRole('" + AMEntitlement.WA_CONFIG_SET + "')")
87 public void set(final Attr value) {
88 waConfigDAO.save(binder.set(value));
89 }
90
91 @PreAuthorize("hasRole('" + AMEntitlement.WA_CONFIG_DELETE + "')")
92 public void delete(final String key) {
93 waConfigDAO.delete(key);
94 }
95
96 protected void registeredServices(final HttpClient client, final String serviceAddress) {
97 String target = StringUtils.appendIfMissing(serviceAddress, "/") + "actuator/registeredServices";
98 client.sendAsync(
99 HttpRequest.newBuilder(URI.create(target)).
100 header(HttpHeaders.AUTHORIZATION, DefaultBasicAuthSupplier.getBasicAuthHeader(
101 securityProperties.getAnonymousUser(), securityProperties.getAnonymousKey())).
102 GET().build(),
103 HttpResponse.BodyHandlers.discarding()).
104 thenAcceptAsync(response -> LOG.info(
105 "Pushed to {} with HTTP status: {}", target, response.statusCode()));
106 }
107
108 protected void refresh(final HttpClient client, final String serviceAddress) {
109 String target = StringUtils.appendIfMissing(serviceAddress, "/") + "actuator/refresh";
110 client.sendAsync(
111 HttpRequest.newBuilder(URI.create(target)).
112 header(HttpHeaders.AUTHORIZATION, DefaultBasicAuthSupplier.getBasicAuthHeader(
113 securityProperties.getAnonymousUser(), securityProperties.getAnonymousKey())).
114 POST(HttpRequest.BodyPublishers.noBody()).build(),
115 HttpResponse.BodyHandlers.discarding()).
116 thenAcceptAsync(response -> LOG.info(
117 "Pushed to {} with HTTP status: {}", target, response.statusCode()));
118 }
119
120 @PreAuthorize("hasRole('" + AMEntitlement.WA_CONFIG_PUSH + "')")
121 public void pushToWA(final WAConfigService.PushSubject subject, final List<String> services) {
122 HttpClient client = HttpClient.newHttpClient();
123 try {
124 serviceOps.list(NetworkService.Type.WA).stream().
125 filter(wa -> CollectionUtils.isEmpty(services) || services.contains(wa.getAddress())).
126 forEach(wa -> {
127 switch (subject) {
128 case clientApps:
129 registeredServices(client, wa.getAddress());
130 break;
131
132 case conf:
133 default:
134 refresh(client, wa.getAddress());
135 }
136 });
137 } catch (KeymasterException e) {
138 throw new NotFoundException("Could not find any WA instance", e);
139 }
140 }
141
142 @Override
143 protected EntityTO resolveReference(final Method method, final Object... args)
144 throws UnresolvedReferenceException {
145
146 throw new UnresolvedReferenceException();
147 }
148 }