/*
* Copyright © 2014 Cask Data, 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 co.cask.cdap.security.auth;
import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.common.io.Codec;
import com.google.common.base.Preconditions;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
/**
* Maintains secret keys used to sign and validate authentication tokens.
* Writes and loads a serialized secret key from file.
*/
public class FileBasedKeyManager extends MapBackedKeyManager {
private final String keyFilePath;
private final Codec<KeyIdentifier> keyIdentifierCodec;
/**
* Create a new FileBasedKeyManager instance that persists keys in a local file.
* @param conf
*/
public FileBasedKeyManager(CConfiguration conf, Codec<KeyIdentifier> keyIdentifierCodec) {
super(conf);
this.keyFilePath = conf.get(Constants.Security.CFG_FILE_BASED_KEYFILE_PATH);
this.keyIdentifierCodec = keyIdentifierCodec;
}
@Override
public void doInit() throws IOException {
File keyFile = new File(keyFilePath);
String keyFileDirectory = keyFile.getParent();
File keyFileDir = new File(keyFileDirectory);
// Create directory for keyfile if it doesn't exist already.
if (!keyFileDir.exists() && !keyFileDir.mkdir()) {
throw new IOException("Failed to create directory " + keyFileDirectory + " for keyfile storage.");
} else {
Preconditions.checkState(keyFileDir.isDirectory(),
"Configured keyFile directory " + keyFileDirectory + " is not a directory!");
Preconditions.checkState(keyFileDir.canRead(),
"Configured keyFile directory " + keyFileDirectory + " exists but is not readable!");
}
// Read existing key from file.
if (keyFile.exists()) {
KeyIdentifier storedKey = keyIdentifierCodec.decode(Files.toByteArray(keyFile));
this.currentKey = storedKey;
// the file-based key is considered valid forever
allKeys.put(storedKey.getKeyId(), storedKey);
} else {
Preconditions.checkState(keyFileDir.canWrite(),
"Configured keyFile directory " + keyFileDirectory + " exists but is not writable!");
// Create a new key and write to file.
generateKey();
keyFile.createNewFile();
Files.write(keyIdentifierCodec.encode(currentKey), keyFile);
}
}
@Override
public void shutDown() {
// nothing to do
}
}