|
@@ -18,8 +18,6 @@
|
|
|
|
|
|
package org.apache.hadoop.security;
|
|
package org.apache.hadoop.security;
|
|
|
|
|
|
-import com.google.protobuf.ByteString;
|
|
|
|
-
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.BufferedInputStream;
|
|
import java.io.DataInput;
|
|
import java.io.DataInput;
|
|
import java.io.DataInputStream;
|
|
import java.io.DataInputStream;
|
|
@@ -27,7 +25,6 @@ import java.io.DataOutput;
|
|
import java.io.DataOutputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.File;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileInputStream;
|
|
-import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
@@ -50,11 +47,9 @@ import org.apache.hadoop.io.Writable;
|
|
import org.apache.hadoop.io.WritableUtils;
|
|
import org.apache.hadoop.io.WritableUtils;
|
|
import org.apache.hadoop.security.token.Token;
|
|
import org.apache.hadoop.security.token.Token;
|
|
import org.apache.hadoop.security.token.TokenIdentifier;
|
|
import org.apache.hadoop.security.token.TokenIdentifier;
|
|
-import org.apache.hadoop.security.proto.SecurityProtos.CredentialsKVProto;
|
|
|
|
-import org.apache.hadoop.security.proto.SecurityProtos.CredentialsProto;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
- * A class that provides the facilities of reading and writing
|
|
|
|
|
|
+ * A class that provides the facilities of reading and writing
|
|
* secret keys and Tokens.
|
|
* secret keys and Tokens.
|
|
*/
|
|
*/
|
|
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
|
|
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
|
|
@@ -63,34 +58,34 @@ public class Credentials implements Writable {
|
|
private static final Log LOG = LogFactory.getLog(Credentials.class);
|
|
private static final Log LOG = LogFactory.getLog(Credentials.class);
|
|
|
|
|
|
private Map<Text, byte[]> secretKeysMap = new HashMap<Text, byte[]>();
|
|
private Map<Text, byte[]> secretKeysMap = new HashMap<Text, byte[]>();
|
|
- private Map<Text, Token<? extends TokenIdentifier>> tokenMap =
|
|
|
|
- new HashMap<Text, Token<? extends TokenIdentifier>>();
|
|
|
|
|
|
+ private Map<Text, Token<? extends TokenIdentifier>> tokenMap =
|
|
|
|
+ new HashMap<Text, Token<? extends TokenIdentifier>>();
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Create an empty credentials instance.
|
|
|
|
|
|
+ * Create an empty credentials instance
|
|
*/
|
|
*/
|
|
public Credentials() {
|
|
public Credentials() {
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Create a copy of the given credentials.
|
|
|
|
|
|
+ * Create a copy of the given credentials
|
|
* @param credentials to copy
|
|
* @param credentials to copy
|
|
*/
|
|
*/
|
|
public Credentials(Credentials credentials) {
|
|
public Credentials(Credentials credentials) {
|
|
this.addAll(credentials);
|
|
this.addAll(credentials);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Returns the Token object for the alias.
|
|
|
|
|
|
+ * Returns the Token object for the alias
|
|
* @param alias the alias for the Token
|
|
* @param alias the alias for the Token
|
|
* @return token for this alias
|
|
* @return token for this alias
|
|
*/
|
|
*/
|
|
public Token<? extends TokenIdentifier> getToken(Text alias) {
|
|
public Token<? extends TokenIdentifier> getToken(Text alias) {
|
|
return tokenMap.get(alias);
|
|
return tokenMap.get(alias);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Add a token in the storage (in memory).
|
|
|
|
|
|
+ * Add a token in the storage (in memory)
|
|
* @param alias the alias for the key
|
|
* @param alias the alias for the key
|
|
* @param t the token object
|
|
* @param t the token object
|
|
*/
|
|
*/
|
|
@@ -101,14 +96,14 @@ public class Credentials implements Writable {
|
|
LOG.warn("Null token ignored for " + alias);
|
|
LOG.warn("Null token ignored for " + alias);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Return all the tokens in the in-memory map.
|
|
|
|
|
|
+ * Return all the tokens in the in-memory map
|
|
*/
|
|
*/
|
|
public Collection<Token<? extends TokenIdentifier>> getAllTokens() {
|
|
public Collection<Token<? extends TokenIdentifier>> getAllTokens() {
|
|
return tokenMap.values();
|
|
return tokenMap.values();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @return number of Tokens in the in-memory map
|
|
* @return number of Tokens in the in-memory map
|
|
*/
|
|
*/
|
|
@@ -117,23 +112,23 @@ public class Credentials implements Writable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Returns the key bytes for the alias.
|
|
|
|
|
|
+ * Returns the key bytes for the alias
|
|
* @param alias the alias for the key
|
|
* @param alias the alias for the key
|
|
* @return key for this alias
|
|
* @return key for this alias
|
|
*/
|
|
*/
|
|
public byte[] getSecretKey(Text alias) {
|
|
public byte[] getSecretKey(Text alias) {
|
|
return secretKeysMap.get(alias);
|
|
return secretKeysMap.get(alias);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @return number of keys in the in-memory map
|
|
* @return number of keys in the in-memory map
|
|
*/
|
|
*/
|
|
public int numberOfSecretKeys() {
|
|
public int numberOfSecretKeys() {
|
|
return secretKeysMap.size();
|
|
return secretKeysMap.size();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Set the key for an alias.
|
|
|
|
|
|
+ * Set the key for an alias
|
|
* @param alias the alias for the key
|
|
* @param alias the alias for the key
|
|
* @param key the key bytes
|
|
* @param key the key bytes
|
|
*/
|
|
*/
|
|
@@ -150,7 +145,7 @@ public class Credentials implements Writable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Return all the secret key entries in the in-memory map.
|
|
|
|
|
|
+ * Return all the secret key entries in the in-memory map
|
|
*/
|
|
*/
|
|
public List<Text> getAllSecretKeys() {
|
|
public List<Text> getAllSecretKeys() {
|
|
List<Text> list = new java.util.ArrayList<Text>();
|
|
List<Text> list = new java.util.ArrayList<Text>();
|
|
@@ -160,13 +155,13 @@ public class Credentials implements Writable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Convenience method for reading a token storage file and loading its Tokens.
|
|
|
|
|
|
+ * Convenience method for reading a token storage file, and loading the Tokens
|
|
|
|
+ * therein in the passed UGI
|
|
* @param filename
|
|
* @param filename
|
|
* @param conf
|
|
* @param conf
|
|
* @throws IOException
|
|
* @throws IOException
|
|
*/
|
|
*/
|
|
- public static Credentials readTokenStorageFile(Path filename,
|
|
|
|
- Configuration conf)
|
|
|
|
|
|
+ public static Credentials readTokenStorageFile(Path filename, Configuration conf)
|
|
throws IOException {
|
|
throws IOException {
|
|
FSDataInputStream in = null;
|
|
FSDataInputStream in = null;
|
|
Credentials credentials = new Credentials();
|
|
Credentials credentials = new Credentials();
|
|
@@ -183,13 +178,13 @@ public class Credentials implements Writable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Convenience method for reading a token storage file and loading its Tokens.
|
|
|
|
|
|
+ * Convenience method for reading a token storage file, and loading the Tokens
|
|
|
|
+ * therein in the passed UGI
|
|
* @param filename
|
|
* @param filename
|
|
* @param conf
|
|
* @param conf
|
|
* @throws IOException
|
|
* @throws IOException
|
|
*/
|
|
*/
|
|
- public static Credentials readTokenStorageFile(File filename,
|
|
|
|
- Configuration conf)
|
|
|
|
|
|
+ public static Credentials readTokenStorageFile(File filename, Configuration conf)
|
|
throws IOException {
|
|
throws IOException {
|
|
DataInputStream in = null;
|
|
DataInputStream in = null;
|
|
Credentials credentials = new Credentials();
|
|
Credentials credentials = new Credentials();
|
|
@@ -204,9 +199,10 @@ public class Credentials implements Writable {
|
|
IOUtils.cleanup(LOG, in);
|
|
IOUtils.cleanup(LOG, in);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Convenience method for reading a token from a DataInputStream.
|
|
|
|
|
|
+ * Convenience method for reading a token storage file directly from a
|
|
|
|
+ * datainputstream
|
|
*/
|
|
*/
|
|
public void readTokenStorageStream(DataInputStream in) throws IOException {
|
|
public void readTokenStorageStream(DataInputStream in) throws IOException {
|
|
byte[] magic = new byte[TOKEN_STORAGE_MAGIC.length];
|
|
byte[] magic = new byte[TOKEN_STORAGE_MAGIC.length];
|
|
@@ -215,36 +211,25 @@ public class Credentials implements Writable {
|
|
throw new IOException("Bad header found in token storage.");
|
|
throw new IOException("Bad header found in token storage.");
|
|
}
|
|
}
|
|
byte version = in.readByte();
|
|
byte version = in.readByte();
|
|
- if (version != TOKEN_STORAGE_VERSION &&
|
|
|
|
- version != OLD_TOKEN_STORAGE_VERSION) {
|
|
|
|
- throw new IOException("Unknown version " + version +
|
|
|
|
|
|
+ if (version != TOKEN_STORAGE_VERSION) {
|
|
|
|
+ throw new IOException("Unknown version " + version +
|
|
" in token storage.");
|
|
" in token storage.");
|
|
}
|
|
}
|
|
- if (version == OLD_TOKEN_STORAGE_VERSION) {
|
|
|
|
- readFields(in);
|
|
|
|
- } else if (version == TOKEN_STORAGE_VERSION) {
|
|
|
|
- readProtos(in);
|
|
|
|
- }
|
|
|
|
|
|
+ readFields(in);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private static final byte[] TOKEN_STORAGE_MAGIC =
|
|
private static final byte[] TOKEN_STORAGE_MAGIC =
|
|
"HDTS".getBytes(Charsets.UTF_8);
|
|
"HDTS".getBytes(Charsets.UTF_8);
|
|
- private static final byte TOKEN_STORAGE_VERSION = 1;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * For backward compatibility.
|
|
|
|
- */
|
|
|
|
- private static final byte OLD_TOKEN_STORAGE_VERSION = 0;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ private static final byte TOKEN_STORAGE_VERSION = 0;
|
|
|
|
+
|
|
public void writeTokenStorageToStream(DataOutputStream os)
|
|
public void writeTokenStorageToStream(DataOutputStream os)
|
|
- throws IOException {
|
|
|
|
|
|
+ throws IOException {
|
|
os.write(TOKEN_STORAGE_MAGIC);
|
|
os.write(TOKEN_STORAGE_MAGIC);
|
|
os.write(TOKEN_STORAGE_VERSION);
|
|
os.write(TOKEN_STORAGE_VERSION);
|
|
- writeProto(os);
|
|
|
|
|
|
+ write(os);
|
|
}
|
|
}
|
|
|
|
|
|
- public void writeTokenStorageFile(Path filename,
|
|
|
|
|
|
+ public void writeTokenStorageFile(Path filename,
|
|
Configuration conf) throws IOException {
|
|
Configuration conf) throws IOException {
|
|
FSDataOutputStream os = filename.getFileSystem(conf).create(filename);
|
|
FSDataOutputStream os = filename.getFileSystem(conf).create(filename);
|
|
writeTokenStorageToStream(os);
|
|
writeTokenStorageToStream(os);
|
|
@@ -252,29 +237,7 @@ public class Credentials implements Writable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * For backward compatibility.
|
|
|
|
- */
|
|
|
|
- public void writeLegacyTokenStorageLocalFile(File f) throws IOException {
|
|
|
|
- writeLegacyOutputStream(new DataOutputStream(new FileOutputStream(f)));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * For backward compatibility.
|
|
|
|
- */
|
|
|
|
- public void writeLegacyTokenStorageFile(Path filename, Configuration conf)
|
|
|
|
- throws IOException {
|
|
|
|
- writeLegacyOutputStream(filename.getFileSystem(conf).create(filename));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void writeLegacyOutputStream(DataOutputStream os) throws IOException {
|
|
|
|
- os.write(TOKEN_STORAGE_MAGIC);
|
|
|
|
- os.write(OLD_TOKEN_STORAGE_VERSION);
|
|
|
|
- write(os);
|
|
|
|
- os.close();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Stores all the keys to DataOutput.
|
|
|
|
|
|
+ * Stores all the keys to DataOutput
|
|
* @param out
|
|
* @param out
|
|
* @throws IOException
|
|
* @throws IOException
|
|
*/
|
|
*/
|
|
@@ -282,12 +245,12 @@ public class Credentials implements Writable {
|
|
public void write(DataOutput out) throws IOException {
|
|
public void write(DataOutput out) throws IOException {
|
|
// write out tokens first
|
|
// write out tokens first
|
|
WritableUtils.writeVInt(out, tokenMap.size());
|
|
WritableUtils.writeVInt(out, tokenMap.size());
|
|
- for(Map.Entry<Text,
|
|
|
|
- Token<? extends TokenIdentifier>> e: tokenMap.entrySet()) {
|
|
|
|
|
|
+ for(Map.Entry<Text,
|
|
|
|
+ Token<? extends TokenIdentifier>> e: tokenMap.entrySet()) {
|
|
e.getKey().write(out);
|
|
e.getKey().write(out);
|
|
e.getValue().write(out);
|
|
e.getValue().write(out);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// now write out secret keys
|
|
// now write out secret keys
|
|
WritableUtils.writeVInt(out, secretKeysMap.size());
|
|
WritableUtils.writeVInt(out, secretKeysMap.size());
|
|
for(Map.Entry<Text, byte[]> e : secretKeysMap.entrySet()) {
|
|
for(Map.Entry<Text, byte[]> e : secretKeysMap.entrySet()) {
|
|
@@ -296,51 +259,9 @@ public class Credentials implements Writable {
|
|
out.write(e.getValue());
|
|
out.write(e.getValue());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Write contents of this instance as CredentialsProto message to DataOutput.
|
|
|
|
- * @param out
|
|
|
|
- * @throws IOException
|
|
|
|
- */
|
|
|
|
- public void writeProto(DataOutput out) throws IOException {
|
|
|
|
- CredentialsProto.Builder storage = CredentialsProto.newBuilder();
|
|
|
|
- for (Map.Entry<Text, Token<? extends TokenIdentifier>> e :
|
|
|
|
- tokenMap.entrySet()) {
|
|
|
|
- CredentialsKVProto.Builder kv = CredentialsKVProto.newBuilder().
|
|
|
|
- setAliasBytes(ByteString.copyFrom(
|
|
|
|
- e.getKey().getBytes(), 0, e.getKey().getLength())).
|
|
|
|
- setToken(e.getValue().toTokenProto());
|
|
|
|
- storage.addTokens(kv.build());
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for(Map.Entry<Text, byte[]> e : secretKeysMap.entrySet()) {
|
|
|
|
- CredentialsKVProto.Builder kv = CredentialsKVProto.newBuilder().
|
|
|
|
- setAliasBytes(ByteString.copyFrom(
|
|
|
|
- e.getKey().getBytes(), 0, e.getKey().getLength())).
|
|
|
|
- setSecret(ByteString.copyFrom(e.getValue()));
|
|
|
|
- storage.addSecrets(kv.build());
|
|
|
|
- }
|
|
|
|
- storage.build().writeTo((DataOutputStream)out);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- * Populates keys/values from proto buffer storage.
|
|
|
|
- * @param in - stream ready to read a serialized proto buffer message
|
|
|
|
- */
|
|
|
|
- public void readProtos(DataInput in) throws IOException {
|
|
|
|
- CredentialsProto storage = CredentialsProto.parseFrom((DataInputStream)in);
|
|
|
|
- for (CredentialsKVProto kv : storage.getTokensList()) {
|
|
|
|
- addToken(new Text(kv.getAliasBytes().toByteArray()),
|
|
|
|
- (Token<? extends TokenIdentifier>) new Token(kv.getToken()));
|
|
|
|
- }
|
|
|
|
- for (CredentialsKVProto kv : storage.getSecretsList()) {
|
|
|
|
- addSecretKey(new Text(kv.getAliasBytes().toByteArray()),
|
|
|
|
- kv.getSecret().toByteArray());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Loads all the keys.
|
|
|
|
|
|
+ * Loads all the keys
|
|
* @param in
|
|
* @param in
|
|
* @throws IOException
|
|
* @throws IOException
|
|
*/
|
|
*/
|
|
@@ -348,7 +269,7 @@ public class Credentials implements Writable {
|
|
public void readFields(DataInput in) throws IOException {
|
|
public void readFields(DataInput in) throws IOException {
|
|
secretKeysMap.clear();
|
|
secretKeysMap.clear();
|
|
tokenMap.clear();
|
|
tokenMap.clear();
|
|
-
|
|
|
|
|
|
+
|
|
int size = WritableUtils.readVInt(in);
|
|
int size = WritableUtils.readVInt(in);
|
|
for(int i=0; i<size; i++) {
|
|
for(int i=0; i<size; i++) {
|
|
Text alias = new Text();
|
|
Text alias = new Text();
|
|
@@ -357,7 +278,7 @@ public class Credentials implements Writable {
|
|
t.readFields(in);
|
|
t.readFields(in);
|
|
tokenMap.put(alias, t);
|
|
tokenMap.put(alias, t);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
size = WritableUtils.readVInt(in);
|
|
size = WritableUtils.readVInt(in);
|
|
for(int i=0; i<size; i++) {
|
|
for(int i=0; i<size; i++) {
|
|
Text alias = new Text();
|
|
Text alias = new Text();
|
|
@@ -368,7 +289,7 @@ public class Credentials implements Writable {
|
|
secretKeysMap.put(alias, value);
|
|
secretKeysMap.put(alias, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Copy all of the credentials from one credential object into another.
|
|
* Copy all of the credentials from one credential object into another.
|
|
* Existing secrets and tokens are overwritten.
|
|
* Existing secrets and tokens are overwritten.
|