/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, Tom Huybrechts
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.security;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.model.*;
import hudson.slaves.Cloud;
import hudson.util.DescriptorList;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.kohsuke.stapler.StaplerRequest;
/**
* Controls authorization throughout Hudson.
*
* <h2>Persistence</h2>
* <p>
* This object will be persisted along with {@link Hudson} object.
* Hudson by itself won't put the ACL returned from {@link #getRootACL()} into the serialized object graph,
* so if that object contains state and needs to be persisted, it's the responsibility of
* {@link AuthorizationStrategy} to do so (by keeping them in an instance field.)
*
* <h2>Re-configuration</h2>
* <p>
* The corresponding {@link Describable} instance will be asked to create a new {@link AuthorizationStrategy}
* every time the system configuration is updated. Implementations that keep more state in ACL beyond
* the system configuration should use {@link Hudson#getAuthorizationStrategy()} to talk to the current
* instance to carry over the state.
*
* @author Kohsuke Kawaguchi
* @see SecurityRealm
*/
public abstract class AuthorizationStrategy extends AbstractDescribableImpl<AuthorizationStrategy> implements ExtensionPoint {
/**
* Returns the instance of {@link ACL} where all the other {@link ACL} instances
* for all the other model objects eventually delegate.
* <p>
* IOW, this ACL will have the ultimate say on the access control.
*/
public abstract ACL getRootACL();
/**
* @deprecated since 1.277
* Override {@link #getACL(Job)} instead.
*/
@Deprecated
public ACL getACL(AbstractProject<?,?> project) {
return getACL((Job)project);
}
public ACL getACL(Job<?,?> project) {
return getRootACL();
}
/**
* Implementation can choose to provide different ACL for different views.
* This can be used as a basis for more fine-grained access control.
*
* <p>
* The default implementation returns the ACL of the ViewGroup.
*
* @since 1.220
*/
public ACL getACL(View item) {
return item.getOwner().getACL();
}
/**
* Implementation can choose to provide different ACL for different items.
* This can be used as a basis for more fine-grained access control.
*
* <p>
* The default implementation returns {@link #getRootACL()}.
*
* @since 1.220
*/
public ACL getACL(AbstractItem item) {
return getRootACL();
}
/**
* Implementation can choose to provide different ACL per user.
* This can be used as a basis for more fine-grained access control.
*
* <p>
* The default implementation returns {@link #getRootACL()}.
*
* @since 1.221
*/
public ACL getACL(User user) {
return getRootACL();
}
/**
* Implementation can choose to provide different ACL for different computers.
* This can be used as a basis for more fine-grained access control.
*
* <p>
* The default implementation delegates to {@link #getACL(Node)}
*
* @since 1.220
*/
public ACL getACL(Computer computer) {
return getACL(computer.getNode());
}
/**
* Implementation can choose to provide different ACL for different {@link Cloud}s.
* This can be used as a basis for more fine-grained access control.
*
* <p>
* The default implementation returns {@link #getRootACL()}.
*
* @since 1.252
*/
public ACL getACL(Cloud cloud) {
return getRootACL();
}
public ACL getACL(Node node) {
return getRootACL();
}
/**
* Returns the list of all group/role names used in this authorization strategy,
* and the ACL returned from the {@link #getRootACL()} method.
* <p>
* This method is used by {@link ContainerAuthentication} to work around the servlet API issue
* that prevents us from enumerating roles that the user has.
* <p>
* If such enumeration is impossible, do the best to list as many as possible, then
* return it. In the worst case, just return an empty list. Doing so would prevent
* users from using role names as group names (see HUDSON-2716 for such one such report.)
*
* @return
* never null.
*/
public abstract Collection<String> getGroups();
/**
* Returns all the registered {@link AuthorizationStrategy} descriptors.
*/
public static DescriptorExtensionList<AuthorizationStrategy,Descriptor<AuthorizationStrategy>> all() {
return Hudson.getInstance().<AuthorizationStrategy,Descriptor<AuthorizationStrategy>>getDescriptorList(AuthorizationStrategy.class);
}
/**
* All registered {@link SecurityRealm} implementations.
*
* @deprecated since 1.286
* Use {@link #all()} for read access, and {@link Extension} for registration.
*/
public static final DescriptorList<AuthorizationStrategy> LIST = new DescriptorList<AuthorizationStrategy>(AuthorizationStrategy.class);
/**
* {@link AuthorizationStrategy} that implements the semantics
* of unsecured Hudson where everyone has full control.
*
* <p>
* This singleton is safe because {@link Unsecured} is stateless.
*/
public static final AuthorizationStrategy UNSECURED = new Unsecured();
public static final class Unsecured extends AuthorizationStrategy implements Serializable {
/**
* Maintains the singleton semantics.
*/
private Object readResolve() {
return UNSECURED;
}
@Override
public ACL getRootACL() {
return UNSECURED_ACL;
}
public Collection<String> getGroups() {
return Collections.emptySet();
}
private static final ACL UNSECURED_ACL = new ACL() {
public boolean hasPermission(Authentication a, Permission permission) {
return true;
}
};
@Extension
public static final class DescriptorImpl extends Descriptor<AuthorizationStrategy> {
public String getDisplayName() {
return Messages.AuthorizationStrategy_DisplayName();
}
@Override
public AuthorizationStrategy newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return UNSECURED;
}
@Override
public String getHelpFile() {
return "/help/security/no-authorization.html";
}
}
}
}