/*
 * Copyright © 2016 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.data2.security;

import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.proto.NamespaceConfig;
import co.cask.cdap.proto.NamespaceMeta;

/**
 * Encapsulates information necessary to impersonate a user - principal and keytab path.
 */
public final class ImpersonationInfo {
  private final String principal;
  private final String keytabURI;

  /**
   * Creates {@link ImpersonationInfo} using the specified principal and keytab path.
   */
  public ImpersonationInfo(String principal, String keytabURI) {
    this.principal = principal;
    this.keytabURI = keytabURI;
  }

  /**
   * Creates {@link ImpersonationInfo} for the specified namespace. If the info is not configured at the namespace
   * level is empty, returns the info configured at the cdap level.
   */
  public ImpersonationInfo(NamespaceMeta namespaceMeta, CConfiguration cConf) {
    NamespaceConfig namespaceConfig = namespaceMeta.getConfig();

    String configuredPrincipal = namespaceConfig.getPrincipal();
    String configuredKeytabURI = namespaceConfig.getKeytabURI();

    if (configuredPrincipal != null && configuredKeytabURI != null) {
      this.principal = configuredPrincipal;
      this.keytabURI = configuredKeytabURI;
    } else if (configuredPrincipal == null && configuredKeytabURI == null) {
      this.principal = cConf.get(Constants.Security.CFG_CDAP_MASTER_KRB_PRINCIPAL);
      this.keytabURI = cConf.get(Constants.Security.CFG_CDAP_MASTER_KRB_KEYTAB_PATH);
    }

    // Ideally, this should never happen, because we make the check upon namespace create.
    // This can technically happen if someone modifies the namespace store directly (i.e. hbase shell PUT).
    throw new IllegalStateException(
      String.format("Either neither or both of the following two configurations must be configured. " +
                      "Configured principal: %s, Configured keytabURI: %s",
                    configuredPrincipal, configuredKeytabURI));
  }

  public String getPrincipal() {
    return principal;
  }

  public String getKeytabURI() {
    return keytabURI;
  }

  @Override
  public String toString() {
    return "ImpersonationInfo{" +
      "principal='" + principal + '\'' +
      ", keytabURI='" + keytabURI + '\'' +
      '}';
  }
}

@@ -2124,18 +2124,26 @@
 );%0A    %7D
-%0A%0A
+ else %7B%0A  
     // I
@@ -2225,16 +2225,18 @@
 create.%0A
+  
     // T
@@ -2339,16 +2339,18 @@
 T).%0A    
+ 
+ 
 throw ne
@@ -2374,16 +2374,18 @@
 eption(%0A
+  
       St
@@ -2502,16 +2502,18 @@
         
+  
 %22Configu
@@ -2558,16 +2558,18 @@
 I: %25s%22,%0A
+  
         
@@ -2624,16 +2624,22 @@
 bURI));%0A
+    %7D%0A
   %7D%0A%0A  p

Correct logic in ImpersonationInfo to only bail if neither keytab nor principal are provided or both are provided