View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.sra.actuate;
20  
21  import com.fasterxml.jackson.core.JsonProcessingException;
22  import com.fasterxml.jackson.databind.json.JsonMapper;
23  import java.time.OffsetDateTime;
24  import java.util.List;
25  import java.util.Objects;
26  import java.util.concurrent.ConcurrentMap;
27  import java.util.stream.Collectors;
28  import org.apache.syncope.common.lib.AMSession;
29  import org.apache.syncope.sra.SessionConfig;
30  import org.apache.syncope.sra.security.cas.CASAuthenticationToken;
31  import org.apache.syncope.sra.security.saml2.SAML2AuthenticationToken;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
35  import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
36  import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
37  import org.springframework.boot.actuate.endpoint.annotation.Selector;
38  import org.springframework.cache.Cache;
39  import org.springframework.cache.CacheManager;
40  import org.springframework.security.core.context.SecurityContext;
41  import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
42  import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
43  import org.springframework.session.MapSession;
44  
45  @Endpoint(id = "sraSessions")
46  public class SRASessions {
47  
48      protected static final Logger LOG = LoggerFactory.getLogger(SRASessions.class);
49  
50      protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
51  
52      protected final CacheManager cacheManager;
53  
54      public SRASessions(final CacheManager cacheManager) {
55          this.cacheManager = cacheManager;
56      }
57  
58      protected static AMSession map(final MapSession mapSession) {
59          SecurityContext ctx = mapSession.getAttribute(
60                  WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME);
61          if (ctx == null) {
62              return null;
63          }
64  
65          AMSession session = new AMSession();
66          session.setKey(mapSession.getId());
67          session.setAuthenticationDate(mapSession.getCreationTime().atOffset(OffsetDateTime.now().getOffset()));
68  
69          String principal;
70          if (ctx.getAuthentication() instanceof SAML2AuthenticationToken) {
71              principal = ((SAML2AuthenticationToken) ctx.getAuthentication()).getPrincipal().getNameId().getValue();
72          } else if (ctx.getAuthentication() instanceof CASAuthenticationToken) {
73              principal = ((CASAuthenticationToken) ctx.getAuthentication()).getPrincipal().getPrincipal().getName();
74          } else if (ctx.getAuthentication() instanceof OAuth2AuthenticationToken) {
75              principal = ((OAuth2AuthenticationToken) ctx.getAuthentication()).getPrincipal().getName();
76          } else {
77              principal = ctx.getAuthentication().getPrincipal().toString();
78          }
79          session.setPrincipal(principal);
80  
81          try {
82              session.setJson(MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(ctx.getAuthentication()));
83          } catch (JsonProcessingException e) {
84              LOG.error("While serializing session {}", mapSession.getId(), e);
85          }
86  
87          return session;
88      }
89  
90      @ReadOperation
91      @SuppressWarnings("unchecked")
92      public List<AMSession> list() {
93          return ((ConcurrentMap<Object, Object>) cacheManager.getCache(SessionConfig.DEFAULT_CACHE).getNativeCache()).
94                  values().stream().map(MapSession.class::cast).map(SRASessions::map).
95                  filter(Objects::nonNull).collect(Collectors.toList());
96      }
97  
98      @ReadOperation
99      public AMSession read(@Selector final String id) {
100         Cache.ValueWrapper value = cacheManager.getCache(SessionConfig.DEFAULT_CACHE).get(id);
101         if (value == null || !(value.get() instanceof MapSession)) {
102             return null;
103         }
104 
105         return map((MapSession) value.get());
106     }
107 
108     @DeleteOperation
109     public void delete(@Selector final String id) {
110         cacheManager.getCache(SessionConfig.DEFAULT_CACHE).evict(id);
111     }
112 }