| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.jackrabbit.oak.spi.security.authorization.cug.impl; |
| |
| import java.security.AccessControlException; |
| import java.security.Principal; |
| import java.util.HashSet; |
| import java.util.Set; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.Session; |
| import javax.jcr.nodetype.PropertyDefinition; |
| |
| import org.apache.jackrabbit.api.JackrabbitSession; |
| import org.apache.jackrabbit.api.security.principal.PrincipalManager; |
| import org.apache.jackrabbit.oak.api.Root; |
| import org.apache.jackrabbit.oak.api.Tree; |
| import org.apache.jackrabbit.oak.api.Type; |
| import org.apache.jackrabbit.oak.namepath.NamePathMapper; |
| import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider; |
| import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters; |
| import org.apache.jackrabbit.oak.spi.security.SecurityProvider; |
| import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration; |
| import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration; |
| import org.apache.jackrabbit.oak.spi.xml.ImportBehavior; |
| import org.apache.jackrabbit.oak.spi.xml.PropInfo; |
| import org.apache.jackrabbit.oak.spi.xml.ProtectedPropertyImporter; |
| import org.apache.jackrabbit.oak.spi.xml.ReferenceChangeTracker; |
| import org.apache.jackrabbit.oak.spi.xml.TextValue; |
| import org.jetbrains.annotations.NotNull; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * CUG specific implementation of the {@code ProtectedPropertyImporter}. |
| */ |
| class CugImporter implements ProtectedPropertyImporter, CugConstants { |
| |
| private static final Logger log = LoggerFactory.getLogger(CugImporter.class); |
| |
| private final MountInfoProvider mountInfoProvider; |
| |
| private boolean initialized; |
| |
| private Set<String> supportedPaths; |
| private int importBehavior; |
| |
| private PrincipalManager principalManager; |
| |
| CugImporter(@NotNull MountInfoProvider mountInfoProvider) { |
| this.mountInfoProvider = mountInfoProvider; |
| } |
| |
| //----------------------------------------------< ProtectedItemImporter >--- |
| @Override |
| public boolean init(@NotNull Session session, @NotNull Root root, @NotNull NamePathMapper namePathMapper, boolean isWorkspaceImport, int uuidBehavior, @NotNull ReferenceChangeTracker referenceTracker, @NotNull SecurityProvider securityProvider) { |
| if (initialized) { |
| throw new IllegalStateException("Already initialized"); |
| } |
| try { |
| ConfigurationParameters config = securityProvider.getConfiguration(AuthorizationConfiguration.class).getParameters(); |
| supportedPaths = CugUtil.getSupportedPaths(config, mountInfoProvider); |
| importBehavior = CugUtil.getImportBehavior(config); |
| |
| if (isWorkspaceImport) { |
| PrincipalConfiguration pConfig = securityProvider.getConfiguration(PrincipalConfiguration.class); |
| principalManager = pConfig.getPrincipalManager(root, namePathMapper); |
| } else { |
| principalManager = ((JackrabbitSession) session).getPrincipalManager(); |
| } |
| initialized = true; |
| } catch (RepositoryException e) { |
| log.warn("Error while initializing cug importer", e); |
| } |
| return initialized; |
| } |
| |
| @Override |
| public void processReferences() throws RepositoryException { |
| // nothing to do |
| } |
| |
| //------------------------------------------< ProtectedPropertyImporter >--- |
| |
| @Override |
| public boolean handlePropInfo(@NotNull Tree parent, @NotNull PropInfo protectedPropInfo, @NotNull PropertyDefinition def) throws RepositoryException { |
| if (CugUtil.definesCug(parent) && isValid(protectedPropInfo, def) && CugUtil.isSupportedPath(parent.getPath(), supportedPaths)) { |
| Set<String> principalNames = new HashSet<>(); |
| for (TextValue txtValue : protectedPropInfo.getTextValues()) { |
| String principalName = txtValue.getString(); |
| Principal principal = principalManager.getPrincipal(principalName); |
| if (principal == null) { |
| switch (importBehavior) { |
| case ImportBehavior.IGNORE: |
| log.debug("Ignoring unknown principal with name '" + principalName + "'."); |
| break; |
| case ImportBehavior.ABORT: |
| throw new AccessControlException("Unknown principal '" + principalName + "'."); |
| case ImportBehavior.BESTEFFORT: |
| log.debug("Importing unknown principal '" + principalName + '\''); |
| principalNames.add(principalName); |
| break; |
| default: |
| throw new IllegalArgumentException("Invalid import behavior " + importBehavior); |
| } |
| } else { |
| principalNames.add(principalName); |
| } |
| } |
| parent.setProperty(REP_PRINCIPAL_NAMES, principalNames, Type.STRINGS); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public void propertiesCompleted(@NotNull Tree protectedParent) throws IllegalStateException, RepositoryException { |
| if (CugUtil.definesCug(protectedParent) && !protectedParent.hasProperty(REP_PRINCIPAL_NAMES)) { |
| // remove the rep:cugPolicy node if mandatory property is missing |
| // (which may also happen upon an attempt to create a cug at an unsupported path). |
| log.debug("Removing incomplete rep:cugPolicy node (due to missing mandatory property or unsupported path)."); |
| protectedParent.remove(); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| private boolean isValid(@NotNull PropInfo propInfo, @NotNull PropertyDefinition def) { |
| if (REP_PRINCIPAL_NAMES.equals(propInfo.getName())) { |
| return def.isMultiple() && NT_REP_CUG_POLICY.equals(def.getDeclaringNodeType().getName()); |
| } |
| return false; |
| } |
| } |