Skip to content

Commit c1d45c9

Browse files
authored
Remove dependency on AEM's KeyStoreService (#879)
Remove Granite JMX dependency for JMX beans Introduce AEM agnostic service interface for which an impl is only registered when running inside AEM (for dealing with user's key stores). Allows starting SCR component AuthorizableInstallerServiceImpl even outside AEM. This closes #878
1 parent 83a2b7c commit c1d45c9

19 files changed

Lines changed: 894 additions & 35 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ See also our talk at [adaptTo() 2016](https://adapt.to/2016/en/schedule/ac-tool.
2929

3030
The AC Tool requires **Java 11 and AEM 6.5.18** or above (use v3.x for older AEM versions which runs on Java 8 and AEM 6.4 or above) for on-premise installations. Since v2.5.0 **[AEM as a Cloud Service](https://www.adobe.com/marketing/experience-manager/cloud-service.html)** is supported, see [Startup Hook](https://github.com/Netcentric/accesscontroltool/blob/develop/docs/ApplyConfig.md#startup-hook) for details.
3131

32-
It is also possible to run the AC Tool on **Apache Sling 12** or above (ensure system user `actool-service` has `jcr:all` permissions on root). When using the AC Tool with Sling, actions in ACE definitions and encrypted passwords cannot be used. To use the `externalId` attribute, ensure bundle `oak-auth-external` installed (not part of default Sling distribution).
32+
It is also possible to run the AC Tool on **Apache Sling 12** or above (ensure system user `actool-service` has `jcr:all` permissions on root). When using the AC Tool with Sling, actions in ACE definitions, encrypted passwords and user's key stores cannot be used. To use the `externalId` attribute, ensure bundle `oak-auth-external` installed (not part of default Sling Starter distribution).
3333

3434
# Installation
3535

accesscontroltool-bundle/bnd.bnd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Bundle-SymbolicName: biz.netcentric.cq.tools.accesscontroltool.bundle
77

88
# allow to run in Sling without AEM bundles
99
# allow to run without bouncycastle which is only necessary for some edge cases when managing keys
10+
# broader version range for JMX annotation as 2.0.0 was introduced in https://github.com/apache/jackrabbit-oak/commit/42b0a70d305372e9c228697012f12c59d643fe27#diff-776354a994a5afefbc8da17a75d83569e198589f2abe3be6890bb621f9a1a708 but is still compatible with our use cases
1011
Import-Package: \
1112
com.adobe.granite.crypto;resolution:=optional,\
1213
com.adobe.granite.keystore;resolution:=optional,\
@@ -15,6 +16,7 @@ com.fasterxml.jackson.databind;resolution:=optional,\
1516
org.apache.http.*;resolution:=optional,\
1617
org.bouncycastle.*;resolution:=optional,\
1718
org.apache.jackrabbit.oak.spi.security.authentication.external.*;resolution:=optional,\
19+
org.apache.jackrabbit.oak.commons.jmx;version="[1.1.0,3.0.0)",\
1820
!jakarta.servlet.jsp.el,\
1921
*
2022

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
-include ../target-osgi-environment/sling-maximum-version-environment/maximum-sling.bndrun
17+

accesscontroltool-bundle/minimum-aem.bndrun

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
-include ../target-osgi-environment/minimum-environment/minimum-aem.bndrun
16+
-include ../target-osgi-environment/aem-minimum-version-environment/minimum-aem.bndrun
1717

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
-include ../target-osgi-environment/sling-minimum-version-environment/minimum-sling.bndrun
17+

accesscontroltool-bundle/pom.xml

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@
117117
<artifactId>oak-jackrabbit-api</artifactId>
118118
<scope>provided</scope>
119119
</dependency>
120+
<!-- for org.apache.jackrabbit.oak.commons.jmx -->
121+
<dependency>
122+
<groupId>org.apache.jackrabbit</groupId>
123+
<artifactId>oak-api</artifactId>
124+
<scope>provided</scope>
125+
</dependency>
126+
<dependency>
127+
<groupId>org.apache.jackrabbit</groupId>
128+
<artifactId>oak-core-spi</artifactId>
129+
<scope>provided</scope>
130+
</dependency>
120131
<dependency>
121132
<groupId>org.apache.jackrabbit.vault</groupId>
122133
<artifactId>org.apache.jackrabbit.vault</artifactId>
@@ -199,12 +210,6 @@
199210
<artifactId>httpclient-osgi</artifactId>
200211
<scope>provided</scope>
201212
</dependency>
202-
<!-- JMX annotations -->
203-
<dependency>
204-
<groupId>com.adobe.granite</groupId>
205-
<artifactId>com.adobe.granite.jmx</artifactId>
206-
<scope>provided</scope>
207-
</dependency>
208213
<!-- Crypto Support -->
209214
<dependency>
210215
<groupId>com.adobe.granite</groupId>
@@ -277,12 +282,6 @@
277282
<scope>test</scope>
278283
</dependency>
279284
<!-- IT dependencies -->
280-
<dependency>
281-
<groupId>org.apache.jackrabbit</groupId>
282-
<artifactId>oak-api</artifactId>
283-
<version>${oak.testing.version}</version>
284-
<scope>test</scope>
285-
</dependency>
286285
<dependency>
287286
<groupId>org.apache.jackrabbit</groupId>
288287
<artifactId>oak-core</artifactId>
@@ -380,11 +379,23 @@
380379
<artifactId>oak-jackrabbit-api</artifactId>
381380
<version>${oak.testing.version}</version>
382381
</additionalClasspathDependency>
382+
<additionalClasspathDependency>
383+
<groupId>org.apache.jackrabbit</groupId>
384+
<artifactId>oak-api</artifactId>
385+
<version>${oak.testing.version}</version>
386+
</additionalClasspathDependency>
387+
<additionalClasspathDependency>
388+
<groupId>org.apache.jackrabbit</groupId>
389+
<artifactId>oak-core-spi</artifactId>
390+
<version>${oak.testing.version}</version>
391+
</additionalClasspathDependency>
383392
</additionalClasspathDependencies>
384393
<classpathDependencyExcludes>
385394
<classpathDependencyExclude>org.apache.jackrabbit:oak-security-spi</classpathDependencyExclude>
386395
<classpathDependencyExclude>org.apache.jackrabbit:oak-auth-external</classpathDependencyExclude>
387-
<classpathDependencyExclude>org.apache.jackrabbit:jackrabbit-api</classpathDependencyExclude>
396+
<classpathDependencyExclude>org.apache.jackrabbit:oak-jackrabbit-api</classpathDependencyExclude>
397+
<classpathDependencyExclude>org.apache.jackrabbit:oak-api</classpathDependencyExclude>
398+
<classpathDependencyExclude>org.apache.jackrabbit:oak-core-spi</classpathDependencyExclude>
388399
</classpathDependencyExcludes>
389400
</configuration>
390401
</plugin>
@@ -412,7 +423,7 @@
412423
<artifactId>bnd-resolver-maven-plugin</artifactId>
413424
<executions>
414425
<execution>
415-
<id>resolve-against-minimum</id>
426+
<id>resolve-against-minimum-aem</id>
416427
<goals>
417428
<goal>resolve</goal>
418429
</goals>
@@ -424,6 +435,32 @@
424435
</bndruns>
425436
</configuration>
426437
</execution>
438+
<execution>
439+
<id>resolve-against-minimum-sling</id>
440+
<goals>
441+
<goal>resolve</goal>
442+
</goals>
443+
<phase>verify</phase>
444+
<configuration>
445+
<useMavenDependencies>false</useMavenDependencies>
446+
<bndruns>
447+
<include>minimum-sling.bndrun</include>
448+
</bndruns>
449+
</configuration>
450+
</execution>
451+
<execution>
452+
<id>resolve-against-maximum-sling</id>
453+
<goals>
454+
<goal>resolve</goal>
455+
</goals>
456+
<phase>verify</phase>
457+
<configuration>
458+
<useMavenDependencies>false</useMavenDependencies>
459+
<bndruns>
460+
<include>maximum-sling.bndrun</include>
461+
</bndruns>
462+
</configuration>
463+
</execution>
427464
<!-- resolving against the maximum, i.e. AEMaaCS version happens separately in the aemanalyser-maven-plugin -->
428465
</executions>
429466
<configuration>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package biz.netcentric.cq.tools.actool.aem;
2+
3+
/*-
4+
* #%L
5+
* Access Control Tool Bundle
6+
* %%
7+
* Copyright (C) 2015 - 2026 Cognizant Netcentric
8+
* %%
9+
* This program and the accompanying materials are made
10+
* available under the terms of the Eclipse Public License 2.0
11+
* which is available at https://www.eclipse.org/legal/epl-2.0/
12+
*
13+
* SPDX-License-Identifier: EPL-2.0
14+
* #L%
15+
*/
16+
17+
import java.security.KeyPair;
18+
import java.security.PrivateKey;
19+
import java.security.cert.Certificate;
20+
21+
import org.apache.sling.api.resource.ResourceResolver;
22+
import org.osgi.service.component.annotations.Component;
23+
import org.osgi.service.component.annotations.Reference;
24+
import org.osgi.service.component.annotations.ReferencePolicyOption;
25+
26+
import com.adobe.granite.keystore.KeyStoreService;
27+
28+
import biz.netcentric.cq.tools.actool.crypto.UserKeyStoreService;
29+
30+
@Component
31+
public class AemUserKeyStoreService implements UserKeyStoreService {
32+
33+
@Reference(policyOption = ReferencePolicyOption.GREEDY)
34+
private KeyStoreService delegate;
35+
36+
@Override
37+
public boolean keyStoreExists(ResourceResolver resourceResolver, String userId) {
38+
return delegate.keyStoreExists(resourceResolver, userId);
39+
}
40+
41+
@Override
42+
public void addKeyStoreKeyEntry(ResourceResolver resourceResolver, String userId, String key, PrivateKey privateKey,
43+
Certificate[] certificates) {
44+
delegate.addKeyStoreKeyEntry(resourceResolver, userId, key, privateKey, certificates);
45+
}
46+
47+
@Override
48+
public void addKeyStoreKeyPair(ResourceResolver resourceResolver, String userId, KeyPair keyPair, String key) {
49+
delegate.addKeyStoreKeyPair(resourceResolver, userId, keyPair, key);
50+
}
51+
52+
@Override
53+
public void createKeyStore(ResourceResolver resourceResolver, String userId, char[] keyStorePasswordCharArray) {
54+
delegate.createKeyStore(resourceResolver, userId, keyStorePasswordCharArray);
55+
}
56+
57+
}

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImpl.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import javax.jcr.RepositoryException;
3737
import javax.jcr.Session;
3838
import javax.jcr.SimpleCredentials;
39-
import javax.jcr.UnsupportedRepositoryOperationException;
4039
import javax.jcr.ValueFactory;
4140

4241
import org.apache.commons.collections4.CollectionUtils;
@@ -61,9 +60,6 @@
6160
import org.slf4j.Logger;
6261
import org.slf4j.LoggerFactory;
6362

64-
import com.adobe.granite.keystore.KeyStoreNotInitialisedException;
65-
import com.adobe.granite.keystore.KeyStoreService;
66-
6763
import biz.netcentric.cq.tools.actool.api.InstallationOptions;
6864
import biz.netcentric.cq.tools.actool.authorizableinstaller.AuthorizableCreatorException;
6965
import biz.netcentric.cq.tools.actool.authorizableinstaller.AuthorizableInstallerService;
@@ -73,6 +69,7 @@
7369
import biz.netcentric.cq.tools.actool.configmodel.pkcs.Key;
7470
import biz.netcentric.cq.tools.actool.configmodel.pkcs.RandomPassword;
7571
import biz.netcentric.cq.tools.actool.crypto.DecryptionService;
72+
import biz.netcentric.cq.tools.actool.crypto.UserKeyStoreService;
7673
import biz.netcentric.cq.tools.actool.externalusermanagement.ExternalGroupManagement;
7774
import biz.netcentric.cq.tools.actool.helper.AcHelper;
7875
import biz.netcentric.cq.tools.actool.helper.AccessControlUtils;
@@ -105,7 +102,7 @@ public class AuthorizableInstallerServiceImpl implements
105102
DecryptionService decryptionService;
106103

107104
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy=ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
108-
volatile KeyStoreService keyStoreService;
105+
volatile UserKeyStoreService keyStoreService;
109106

110107
@Reference(policyOption = ReferencePolicyOption.GREEDY)
111108
ResourceResolverFactory resourceResolverFactory;
@@ -218,7 +215,7 @@ private void installAuthorizableConfigurationBean(final Session session,
218215
}
219216
}
220217

221-
private void installKeys(boolean appendToKeyStore, User user, Map<String, Key> keys, String userId, String keyStorePassword, Session session, InstallationLogger installLog) throws LoginException, SlingIOException, SecurityException, KeyStoreNotInitialisedException, IOException, GeneralSecurityException, UnsupportedRepositoryOperationException, RepositoryException {
218+
private void installKeys(boolean appendToKeyStore, User user, Map<String, Key> keys, String userId, String keyStorePassword, Session session, InstallationLogger installLog) throws LoginException, SlingIOException, SecurityException, IOException, RepositoryException {
222219
Map<String, Object> authInfo = new HashMap<>();
223220
authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
224221
ResourceResolver resolver = resourceResolverFactory.getResourceResolver(authInfo);
@@ -234,7 +231,7 @@ private void installKeys(boolean appendToKeyStore, User user, Map<String, Key> k
234231
}
235232
}
236233

237-
private void removeKeyStore(ResourceResolver resolver, User user, InstallationLogger installLog) throws UnsupportedRepositoryOperationException, RepositoryException, PersistenceException {
234+
private void removeKeyStore(ResourceResolver resolver, User user, InstallationLogger installLog) throws RepositoryException, PersistenceException {
238235
String keyStorePath = user.getPath() + "/" + USER_KEYSTORE_FOLDER;
239236
Resource keyStoreResource = resolver.getResource(keyStorePath);
240237
if (keyStoreResource != null) {
@@ -245,7 +242,7 @@ private void removeKeyStore(ResourceResolver resolver, User user, InstallationLo
245242
}
246243
}
247244

248-
private void installKeys(Map<String, Key> keys, String userId, String keyStorePassword, ResourceResolver resourceResolver, InstallationLogger installLog) throws SlingIOException, SecurityException, KeyStoreNotInitialisedException, IOException, GeneralSecurityException {
245+
private void installKeys(Map<String, Key> keys, String userId, String keyStorePassword, ResourceResolver resourceResolver, InstallationLogger installLog) throws SlingIOException, SecurityException {
249246
if (keyStoreService == null) {
250247
throw new IllegalStateException(
251248
"Keys are used on the authorizable which require the AEM KeyStore Service which is missing.");
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package biz.netcentric.cq.tools.actool.crypto;
2+
3+
/*-
4+
* #%L
5+
* Access Control Tool Bundle
6+
* %%
7+
* Copyright (C) 2015 - 2026 Cognizant Netcentric
8+
* %%
9+
* This program and the accompanying materials are made
10+
* available under the terms of the Eclipse Public License 2.0
11+
* which is available at https://www.eclipse.org/legal/epl-2.0/
12+
*
13+
* SPDX-License-Identifier: EPL-2.0
14+
* #L%
15+
*/
16+
17+
import java.security.KeyPair;
18+
import java.security.PrivateKey;
19+
import java.security.cert.Certificate;
20+
21+
import org.apache.sling.api.resource.ResourceResolver;
22+
23+
/** Interface for managing user's key stores.
24+
* This allows to decouple from a concrete (AEM-specific) interface like {@link com.adobe.granite.keystore.KeyStoreService} */
25+
public interface UserKeyStoreService {
26+
27+
boolean keyStoreExists(ResourceResolver resourceResolver, String userId);
28+
29+
void addKeyStoreKeyEntry(ResourceResolver resourceResolver, String userId, String key, PrivateKey privateKey,
30+
Certificate[] certificates);
31+
32+
void addKeyStoreKeyPair(ResourceResolver resourceResolver, String userId, KeyPair keyPair, String key);
33+
34+
void createKeyStore(ResourceResolver resourceResolver, String userId, char[] keyStorePasswordCharArray);
35+
36+
}

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/jmx/AceServiceMBean.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616

1717
import javax.jcr.RepositoryException;
1818

19-
import com.adobe.granite.jmx.annotation.Description;
20-
import com.adobe.granite.jmx.annotation.Name;
19+
import org.apache.jackrabbit.oak.api.jmx.Description;
20+
import org.apache.jackrabbit.oak.api.jmx.Name;
21+
2122

2223
/**
2324
* exposes functionalities of the Netcentric AC-Tool

0 commit comments

Comments
 (0)