001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.yarn.security.client;
020
021 import javax.crypto.SecretKey;
022
023 import org.apache.hadoop.classification.InterfaceAudience.Public;
024 import org.apache.hadoop.classification.InterfaceStability.Evolving;
025 import org.apache.hadoop.security.token.SecretManager;
026 import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
027
028 /**
029 * A simple {@link SecretManager} for AMs to validate Client-RM tokens issued to
030 * clients by the RM using the underlying master-key shared by RM to the AMs on
031 * their launch. All the methods are called by either Hadoop RPC or YARN, so
032 * this class is strictly for the purpose of inherit/extend and register with
033 * Hadoop RPC.
034 */
035 @Public
036 @Evolving
037 public class ClientToAMTokenSecretManager extends
038 BaseClientToAMTokenSecretManager {
039 private static final int MASTER_KEY_WAIT_MSEC = 10 * 1000;
040
041 // Only one master-key for AM
042 private volatile SecretKey masterKey;
043
044 public ClientToAMTokenSecretManager(
045 ApplicationAttemptId applicationAttemptID, byte[] key) {
046 super();
047 if (key != null) {
048 this.masterKey = SecretManager.createSecretKey(key);
049 } else {
050 this.masterKey = null;
051 }
052
053 }
054
055 @Override
056 public byte[] retrievePassword(ClientToAMTokenIdentifier identifier)
057 throws InvalidToken {
058 if (this.masterKey == null) {
059 synchronized (this) {
060 while (masterKey == null) {
061 try {
062 wait(MASTER_KEY_WAIT_MSEC);
063 break;
064 } catch (InterruptedException e) {
065 }
066 }
067 }
068 }
069 return super.retrievePassword(identifier);
070 }
071
072 @Override
073 public SecretKey getMasterKey(ApplicationAttemptId applicationAttemptID) {
074 // Only one master-key for AM, just return that.
075 return this.masterKey;
076 }
077
078 public void setMasterKey(byte[] key) {
079 synchronized (this) {
080 this.masterKey = SecretManager.createSecretKey(key);
081 notifyAll();
082 }
083 }
084 }