| // Copyright 2008 Google Inc. |
| // |
| // Licensed 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 com.google.enterprise.secmgr.config; |
| |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| |
| /** |
| * A base class for implementing a configuration encode/decode class. |
| */ |
| public abstract class ConfigCodec { |
| |
| /** |
| * Decode a configuration from a string. |
| * |
| * @param string The string to decode. |
| * @return A configuration. |
| * @throws IOException if there are errors while reading the configuration. |
| * @throws ConfigException if the configuration is malformed. |
| */ |
| public SecurityManagerConfig readConfig(String string) |
| throws IOException, ConfigException { |
| return readConfig(new StringReader(string)); |
| } |
| |
| /** |
| * Encode a configuration as a string. |
| * |
| * @param config The configuration to be encoded. |
| * @return The encoded string. |
| * @throws IOException if there are errors while writing the configuration. |
| */ |
| public String configToString(SecurityManagerConfig config) throws IOException { |
| Writer writer = new StringWriter(); |
| writeConfig(config, writer); |
| return writer.toString(); |
| } |
| |
| /** |
| * Read and decode a configuration from a given source. |
| * |
| * @param reader The source to read the encoded configuration from. |
| * @return A configuration. |
| * @throws IOException if there are errors while reading the configuration. |
| * @throws ConfigException if the configuration is malformed. |
| */ |
| public SecurityManagerConfig readConfig(Reader reader) |
| throws IOException, ConfigException { |
| SecurityManagerConfig config = readConfigInternal(reader); |
| guaranteeValidConfig(config); |
| return config; |
| } |
| |
| /** |
| * Read and decode a configuration from a given file. |
| * |
| * @param file The file to read the encoded configuration from. |
| * @return A configuration. |
| * @throws IOException if there are errors while reading the configuration. |
| * @throws ConfigException if the configuration is malformed. |
| */ |
| public SecurityManagerConfig readConfig(File file) |
| throws IOException, ConfigException { |
| Reader reader = new FileReader(file); |
| try { |
| return readConfig(reader); |
| } finally { |
| reader.close(); |
| } |
| } |
| |
| protected abstract SecurityManagerConfig readConfigInternal(Reader reader) |
| throws IOException, ConfigException; |
| |
| /** |
| * Encode and write a configuration to a given sink. |
| * |
| * @param config The configuration to be encoded. |
| * @param writer The sink to write the encoded configuration to. |
| * @throws IOException if there are errors while writing the configuration. |
| */ |
| public void writeConfig(SecurityManagerConfig config, Writer writer) throws IOException { |
| guaranteeValidConfig(config); |
| writeConfigInternal(config, writer); |
| } |
| |
| protected abstract void writeConfigInternal(SecurityManagerConfig config, Writer writer) |
| throws IOException; |
| |
| private void guaranteeValidConfig(SecurityManagerConfig config) { |
| if (!isValidConfig(config)) { |
| throw new IllegalStateException("Config is not valid: " + config); |
| } |
| } |
| |
| /** |
| * A valid config must contain a "default" group and that group must require a |
| * username, be non-optional, and non-empty. This in turn ensures that a saml |
| * assertion from the security manager will always contain a username which |
| * can in turn be used when creating policy ACLs. |
| * |
| * TODO(martincochran): ensure that EFE gets the right username and/or that |
| * the correct saml subject is generated by the security manager. |
| */ |
| private boolean isValidConfig(SecurityManagerConfig config) { |
| |
| return true; |
| /* TODO(kstillson): I'm disabling this check. It was added to address |
| * to address the concern that PVI assignment may not be stable- specifically, |
| * user1 has a forms auth cookie before any interaction with the GSA, if the |
| * default CG does not insist on requires-username, then CG will be satisfied |
| * but no username is set, so the PVI could come from somewhere else (e.g. |
| * kerberos). However, user2 has no cookie, so they get a ULF, and the PVI |
| * is set by their forms login. That is a problem, however, this solution |
| * is too drastic, and eliminates numerous valid use-cases (such as a sec-mgr |
| * that does nothing but a single forms-auth CG that doesn't need a username). |
| * So We're going to have to find a more subtle solution to the original |
| * problem. |
| |
| if (config.isEmpty()) { |
| return true; |
| } |
| boolean defaultGroupEmpty = false; |
| boolean someGroupNonEmpty = false; |
| |
| for (CredentialsGroup group : config) { |
| if ("default".equalsIgnoreCase(group.getName())) { |
| if (!group.getRequiresUsername()) { |
| return false; |
| } |
| if (group.getIsOptional()) { |
| return false; |
| } |
| if (!group.getElements().isEmpty()) { |
| return true; |
| } |
| } |
| if (!group.getElements().isEmpty()) { |
| someGroupNonEmpty = true; |
| } |
| } |
| return !someGroupNonEmpty; |
| */ |
| } |
| } |