blob: 203bbbe7e0b5e5c2a793284a5c9ccfa79b172a2a [file] [log] [blame]
// Copyright 2011 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.authncontroller;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.enterprise.secmgr.config.ConfigSingleton;
import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
import com.google.enterprise.secmgr.json.TypeAdapters;
import com.google.enterprise.secmgr.json.TypeProxy;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* This is the state exported from the security manager to the GSA after a
* successful authentication. It is also the format that the security manager
* accepts from client SAML providers if they choose to provide this
* information.
*/
@Immutable
@ParametersAreNonnullByDefault
public final class ExportedState {
@Nonnull public static final String ATTRIBUTE_NAME = "SecurityManagerState";
@Nonnegative public static final int CURRENT_VERSION = 1;
@Nonnegative public static final int MIN_VERSION = 1;
@Nonnegative public static final int MAX_VERSION = 1;
/**
* This class represents simple credentials without the complex structure used
* by the security manager.
*/
@Immutable
@ParametersAreNonnullByDefault
public static final class Credentials {
@Nonnull public static final Credentials EMPTY
= new Credentials(null, null, null, ImmutableSet.<String>of());
@Nullable private final String username;
@Nullable private final String domain;
@Nullable private final String password;
@Nonnull private final ImmutableSet<String> groups;
private Credentials(@Nullable String username, @Nullable String domain,
@Nullable String password, ImmutableSet<String> groups) {
this.username = username;
this.domain = domain;
this.password = password;
this.groups = groups;
}
/**
* Gets a new credentials instance.
*
* @param username The username credential or {@code null}.
* @param domain The domain credential or {@code null}.
* @param password The password credential or {@code null}.
* @param groups The group credentials.
* @return An immutable structure of the given credentials.
*/
@CheckReturnValue
@Nonnull
public static Credentials make(@Nullable String username, @Nullable String domain,
@Nullable String password, Iterable<String> groups) {
return new Credentials(username, domain, password, ImmutableSet.copyOf(groups));
}
/**
* Gets a new credentials instance with no groups.
*
* @param username The username credential or {@code null}.
* @param domain The domain credential or {@code null}.
* @param password The password credential or {@code null}.
* @return An immutable structure of the given credentials.
*/
@CheckReturnValue
@Nonnull
public static Credentials make(@Nullable String username, @Nullable String domain,
@Nullable String password) {
return make(username, domain, password, ImmutableSet.<String>of());
}
/**
* Gets this instance's username.
*/
@CheckReturnValue
@Nullable
public String getUsername() {
return username;
}
/**
* Gets this instance's domain.
*/
@CheckReturnValue
@Nullable
public String getDomain() {
return domain;
}
/**
* Gets this instance's password.
*/
@CheckReturnValue
@Nullable
public String getPassword() {
return password;
}
/**
* Gets this instance's groups as an immutable set.
*/
@CheckReturnValue
@Nonnull
public ImmutableSet<String> getGroups() {
return groups;
}
@Override
public boolean equals(Object object) {
if (object == this) { return true; }
if (!(object instanceof Credentials)) { return false; }
Credentials other = (Credentials) object;
return Objects.equal(getUsername(), other.getUsername())
&& Objects.equal(getDomain(), other.getDomain())
&& Objects.equal(getPassword(), other.getPassword())
&& Objects.equal(getGroups(), other.getGroups());
}
@Override
public int hashCode() {
return Objects.hashCode(getUsername(), getDomain(), getPassword(), getGroups());
}
@Override
public String toString() {
return ConfigSingleton.getGson().toJson(this);
}
private static final class LocalProxy implements TypeProxy<Credentials> {
String username;
String domain;
String password;
ImmutableSet<String> groups;
@SuppressWarnings("unused")
LocalProxy() {
}
@SuppressWarnings("unused")
LocalProxy(Credentials credentials) {
username = credentials.getUsername();
domain = credentials.getDomain();
password = credentials.getPassword();
groups = credentials.getGroups();
}
@Override
public Credentials build() {
return Credentials.make(username, domain, password, groups);
}
}
}
@Nonnegative private final int version;
@Nonnegative private final long timeStamp;
@Nonnull private final Credentials pviCredentials;
@Nonnull private final Credentials basicCredentials;
@Nonnull private final ImmutableMap<String, Credentials> connectorCredentials;
private ExportedState(@Nonnegative int version, @Nonnegative long timeStamp,
Credentials pviCredentials, Credentials basicCredentials,
ImmutableMap<String, Credentials> connectorCredentials) {
this.version = version;
this.timeStamp = timeStamp;
this.pviCredentials = pviCredentials;
this.basicCredentials = basicCredentials;
this.connectorCredentials = connectorCredentials;
}
/**
* Gets the time at which this state was frozen.
*/
@CheckReturnValue
@Nonnegative
public long getTimeStamp() {
return timeStamp;
}
/**
* Gets the credentials for the Primary Verified Identity (PVI).
*/
@CheckReturnValue
@Nonnull
public Credentials getPviCredentials() {
return pviCredentials;
}
/**
* If the security manager is configured for HTTP Basic or NTLM
* authentication, this gets the credentials for that mechanism.
*/
@CheckReturnValue
@Nonnull
public Credentials getBasicCredentials() {
return basicCredentials;
}
/**
* If the security manager is configured for connector authentication, this
* gets the credentials corresponding to each configured connector.
*/
@CheckReturnValue
@Nonnull
public ImmutableMap<String, Credentials> getConnectorCredentials() {
return connectorCredentials;
}
/**
* Gets a JSON string representation for this object.
*/
@CheckReturnValue
@Nonnull
public String toJsonString() {
return ConfigSingleton.getGson().toJson(this);
}
/**
* Decodes a JSON string representation into an exported-state object.
*/
@CheckReturnValue
@Nonnull
public static ExportedState fromJsonString(String jsonString) {
return ConfigSingleton.getGson().fromJson(jsonString, ExportedState.class);
}
public static void registerTypeAdapters(GsonBuilder builder) {
builder.registerTypeAdapter(Credentials.class,
ProxyTypeAdapter.make(Credentials.class, Credentials.LocalProxy.class));
builder.registerTypeAdapter(ExportedState.class,
ProxyTypeAdapter.make(ExportedState.class, LocalProxy.class));
builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
TypeAdapters.immutableSet());
builder.registerTypeAdapter(new TypeToken<ImmutableMap<String, Credentials>>() {}.getType(),
TypeAdapters.immutableMap());
}
private static final class LocalProxy implements TypeProxy<ExportedState> {
int version;
long timeStamp;
Credentials pviCredentials;
Credentials basicCredentials;
ImmutableMap<String, Credentials> connectorCredentials;
@SuppressWarnings("unused")
LocalProxy() {
}
@SuppressWarnings("unused")
LocalProxy(ExportedState state) {
version = state.version;
timeStamp = state.timeStamp;
pviCredentials = state.getPviCredentials();
basicCredentials = state.getBasicCredentials();
connectorCredentials = state.getConnectorCredentials();
}
@Override
public ExportedState build() {
Preconditions.checkArgument(version >= MIN_VERSION && version <= MAX_VERSION);
Preconditions.checkArgument(timeStamp >= 0);
return new ExportedState(version, timeStamp, pviCredentials, basicCredentials,
ImmutableMap.copyOf(connectorCredentials));
}
}
}