1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.security.util;
23
24 import static org.apache.commons.lang3.StringUtils.isBlank;
25 import static org.opencastproject.security.api.SecurityConstants.EPISODE_ROLE_ID_PREFIX;
26 import static org.opencastproject.security.api.SecurityConstants.GLOBAL_ADMIN_ROLE;
27 import static org.opencastproject.security.api.SecurityConstants.GLOBAL_ANONYMOUS_USERNAME;
28 import static org.opencastproject.security.api.SecurityConstants.GLOBAL_CAPTURE_AGENT_ROLE;
29 import static org.opencastproject.util.data.Tuple.tuple;
30
31 import org.opencastproject.security.api.JaxbOrganization;
32 import org.opencastproject.security.api.JaxbRole;
33 import org.opencastproject.security.api.JaxbUser;
34 import org.opencastproject.security.api.Organization;
35 import org.opencastproject.security.api.OrganizationDirectoryService;
36 import org.opencastproject.security.api.SecurityConstants;
37 import org.opencastproject.security.api.SecurityService;
38 import org.opencastproject.security.api.UnauthorizedException;
39 import org.opencastproject.security.api.User;
40 import org.opencastproject.security.api.UserDirectoryService;
41 import org.opencastproject.util.ConfigurationException;
42 import org.opencastproject.util.NotFoundException;
43 import org.opencastproject.util.data.Tuple;
44
45 import org.apache.commons.lang3.StringUtils;
46 import org.osgi.service.component.ComponentContext;
47
48 import java.net.URL;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.Map;
52 import java.util.Optional;
53 import java.util.regex.Pattern;
54
55
56 public final class SecurityUtil {
57 private static final Pattern SANITIZING_PATTERN = Pattern.compile("[^a-zA-Z0-9_]");
58
59 private SecurityUtil() {
60 }
61
62
63 public static final String PROPERTY_KEY_SYS_USER = "org.opencastproject.security.digest.user";
64
65 public static final String PROPERTY_KEY_ACL_ADDITIONAL_ACTIONS = "org.opencastproject.acl.additional.actions.";
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public static void runAs(SecurityService sec, Organization org, User user, Runnable fn) {
80 final Organization prevOrg = sec.getOrganization();
81 final User prevUser = prevOrg != null ? sec.getUser() : null;
82 sec.setOrganization(org);
83 sec.setUser(user);
84 try {
85 fn.run();
86 } finally {
87 sec.setOrganization(prevOrg);
88 sec.setUser(prevUser);
89 }
90 }
91
92
93
94
95
96
97
98
99
100 public static User createSystemUser(String systemUserName, Organization org) {
101 JaxbOrganization jaxbOrganization = JaxbOrganization.fromOrganization(org);
102 return new JaxbUser(systemUserName, null, jaxbOrganization, new JaxbRole(GLOBAL_ADMIN_ROLE, jaxbOrganization),
103 new JaxbRole(org.getAdminRole(), jaxbOrganization));
104 }
105
106
107
108
109
110
111
112
113 public static User createAnonymousUser(Organization org) {
114 JaxbOrganization jaxbOrganization = JaxbOrganization.fromOrganization(org);
115 return new JaxbUser(GLOBAL_ANONYMOUS_USERNAME, null, jaxbOrganization, new JaxbRole(
116 jaxbOrganization.getAnonymousRole(), jaxbOrganization));
117 }
118
119
120
121
122
123
124
125 public static User createSystemUser(ComponentContext cc, Organization org) {
126 final String systemUserName = cc.getBundleContext().getProperty(PROPERTY_KEY_SYS_USER);
127 return createSystemUser(systemUserName, org);
128 }
129
130
131
132
133
134
135 public static String getSystemUserName(ComponentContext cc) {
136 final String systemUserName = cc.getBundleContext().getProperty(PROPERTY_KEY_SYS_USER);
137 if (systemUserName != null) {
138 return systemUserName;
139 } else {
140 throw new ConfigurationException(
141 "An Opencast installation always needs a system user name. Please configure one under the key "
142 + PROPERTY_KEY_SYS_USER);
143 }
144 }
145
146
147
148
149 public static Optional<Tuple<User, Organization>> getUserAndOrganization(SecurityService sec,
150 OrganizationDirectoryService orgDir, String orgId, UserDirectoryService userDir, String userId) {
151 final Organization prevOrg = sec.getOrganization();
152 try {
153 final Organization org = orgDir.getOrganization(orgId);
154 sec.setOrganization(org);
155 return Optional.ofNullable(userDir.loadUser(userId))
156 .map(user -> tuple(user, org));
157 } catch (NotFoundException e) {
158 return Optional.empty();
159 } finally {
160 sec.setOrganization(prevOrg);
161 }
162 }
163
164
165 public static Tuple<String, Integer> hostAndPort(URL url) {
166 int port = url.getPort();
167 if (port < 0) {
168 port = url.getDefaultPort();
169 }
170 return tuple(StringUtils.strip(url.getHost(), "/"), port);
171 }
172
173
174
175
176
177
178
179
180 public static void checkAgentAccess(final SecurityService securityService, final String agentId)
181 throws UnauthorizedException {
182 if (isBlank(agentId)) {
183 return;
184 }
185 final User user = securityService.getUser();
186 if (user.hasRole(SecurityConstants.GLOBAL_ADMIN_ROLE) || user.hasRole(user.getOrganization().getAdminRole())) {
187 return;
188 }
189 if (!user.hasRole(SecurityUtil.getCaptureAgentRole(agentId))) {
190 throw new UnauthorizedException(user, "schedule");
191 }
192 }
193
194
195
196
197
198
199
200
201 public static Map<String, String> additionalAclActions(final Organization organization) {
202 Map<String, String> additionalActions = new HashMap<>();
203 organization.getProperties().forEach((key, value) -> {
204 if (key.startsWith(PROPERTY_KEY_ACL_ADDITIONAL_ACTIONS)) {
205 additionalActions.put(key.substring(PROPERTY_KEY_ACL_ADDITIONAL_ACTIONS.length()), value);
206 }
207 });
208 return Collections.unmodifiableMap(additionalActions);
209 }
210
211 private static String sanitizeCaName(final String ca) {
212 return SANITIZING_PATTERN.matcher(ca).replaceAll("").toUpperCase();
213 }
214
215
216
217
218
219
220
221
222
223 public static String getCaptureAgentRole(final String agentId) {
224 return GLOBAL_CAPTURE_AGENT_ROLE + "_" + sanitizeCaName(agentId);
225 }
226
227
228
229
230
231
232
233
234 public static String getEpisodeRoleId(final String mediaPackageId, final String action) {
235 return EPISODE_ROLE_ID_PREFIX + "_" + mediaPackageId + "_" + action.toUpperCase();
236 }
237 }