/*****************************************************************************
* Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved.
* 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.vmware.bdd.cli.commands;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.stereotype.Component;
import com.vmware.bdd.apitypes.UserMgmtServer;
import com.vmware.bdd.cli.rest.CliRestException;
import com.vmware.bdd.cli.rest.MgmtVMCfgClient;
import com.vmware.bdd.cli.rest.UserMgmtServerRestClient;
import com.vmware.bdd.exception.ValidationException;
import com.vmware.bdd.security.tls.TlsHelper;
import com.vmware.bdd.security.tls.UntrustedCertificateException;
import com.vmware.bdd.usermgmt.UserMgmtConstants;
import com.vmware.bdd.usermgmt.UserMgmtMode;
import com.vmware.bdd.validation.ValidationErrorsStringBuilder;
@Component
public class UserMgmtServerCommands implements CommandMarker {
@Autowired
private UserMgmtServerRestClient userMgmtServerRestClient;
@Autowired
private MgmtVMCfgClient mgmtCfgOnMgmtVMClient;
@CliAvailabilityIndicator({"usermgmtserver help"})
public boolean isCommandAvailable() {
return true;
}
@CliCommand(value = "usermgmtserver get", help = "get the default AD/LDAP server info.")
public void getUserMgmtServer(
) {
try {
UserMgmtServer userMgmtServer = userMgmtServerRestClient.get(UserMgmtConstants.DEFAULT_USERMGMT_SERVER_NAME);
if(userMgmtServer == null) {
System.out.println("The AD/LDAP server is not added.");
return;
}
LinkedHashMap<String, List<String>> distroColumnNamesWithGetMethodNames =
new LinkedHashMap<String, List<String>>();
distroColumnNamesWithGetMethodNames.put(
"TYPE", Arrays.asList("getType"));
distroColumnNamesWithGetMethodNames
.put("PRIMARY URL", Arrays.asList("getPrimaryUrl"));
distroColumnNamesWithGetMethodNames
.put("LOGIN", Arrays.asList("getUserName"));
distroColumnNamesWithGetMethodNames
.put("PASSWORD", Arrays.asList("getPassword"));
distroColumnNamesWithGetMethodNames.put(
"GROUP SEARCH BASE", Arrays.asList("getBaseGroupDn"));
distroColumnNamesWithGetMethodNames.put(
"USER SEARCH BASE", Arrays.asList("getBaseUserDn"));
distroColumnNamesWithGetMethodNames.put(
"MANAGEMENT VM USER GROUP", Arrays.asList("getMgmtVMUserGroupDn"));
userMgmtServer.setPassword("******");
try {
CommandsUtils.printInTableFormat(
distroColumnNamesWithGetMethodNames, new Object[]{userMgmtServer},
Constants.OUTPUT_INDENT);
} catch (Exception e) {
CommandOutputHelper.GET_LDAP_OUTPUT.printFailure(e);
}
} catch (CliRestException e) {
CommandOutputHelper.GET_LDAP_OUTPUT.printFailure(e);
}
}
@CliCommand(value = "usermgmtserver modify", help = "Change the default AD/LDAP server info.")
public void modifyUserMgmtServer(
@CliOption(key = {"cfgfile"}, mandatory = true, help = "The AD/LDAP server configuration JSON file path.") final String cfgFilePath,
@CliOption(key = {"trustCertificate"}, mandatory = false, help = "Trust the server certificate.") final Boolean trustCertificateFlag) {
final UserMgmtServer userMgmtServer = parseUserMgmtServer(cfgFilePath, CommandOutputHelper.MODIFY_LDAP_OUTPUT);
if (userMgmtServer == null) {
return;
}
userMgmtServer.setName(UserMgmtConstants.DEFAULT_USERMGMT_SERVER_NAME);
try {
try {
userMgmtServerRestClient.modifyUserMgmtServer(userMgmtServer,
trustCertificateFlag == null ? false : trustCertificateFlag);
CommandOutputHelper.MODIFY_LDAP_OUTPUT.printSuccess();
} catch (UntrustedCertificateException e) {
if (handleUntrustedCertificate(e, CommandOutputHelper.MODIFY_LDAP_OUTPUT,
new Runnable() {
@Override
public void run() {
userMgmtServerRestClient.modifyUserMgmtServer(userMgmtServer, true);
}
})) {
CommandOutputHelper.MODIFY_LDAP_OUTPUT.printSuccess();
}
}
} catch (CliRestException e) {
CommandOutputHelper.MODIFY_LDAP_OUTPUT.printFailure(e.getMessage());
} catch (ValidationException e) {
handleValidationErrors(e, CommandOutputHelper.MODIFY_LDAP_OUTPUT);
}
}
@CliCommand(value = "usermgmtserver add", help = "Add an AD/LDAP server as the default user management server for VMs.")
public void addUserMgmtServer(
@CliOption(key = {"cfgfile"}, mandatory = true, help = "The AD/LDAP server configuration JSON file path.") final String cfgFilePath,
@CliOption(key = {"trustCertificate"}, mandatory = false, help = "Trust the server certificate.") final Boolean trustCertificateFlag
/*,@CliOption(key = {"enableOnMgmtVM"}, mandatory = true, help = "Enable the new AD/LDAP server on management VM.") final boolean enableOnMgmtVM*/) {
try {
final UserMgmtServer userMgmtServer = parseUserMgmtServer(cfgFilePath, CommandOutputHelper.MODIFY_LDAP_OUTPUT);
if (userMgmtServer == null) {
return;
}
userMgmtServer.setName(UserMgmtConstants.DEFAULT_USERMGMT_SERVER_NAME);
boolean continued = false;
try {
userMgmtServerRestClient.addUserMgmtServer(userMgmtServer,
trustCertificateFlag == null ? false : trustCertificateFlag);
continued = true;
} catch (UntrustedCertificateException e) {
continued = handleUntrustedCertificate(e, CommandOutputHelper.ADD_LDAP_OUTPUT,
new Runnable() {
@Override
public void run() {
userMgmtServerRestClient.addUserMgmtServer(userMgmtServer, true);
}
});
}
if (continued) {
try {
mgmtCfgOnMgmtVMClient.config(UserMgmtMode.MIXED.name());
} catch (Exception e1) {
CommandOutputHelper.ADD_LDAP_OUTPUT.printFailure(e1);
System.out.println("Try to recover the old server configuration.");
userMgmtServerRestClient.removeUserMgmtServer(userMgmtServer.getName());
System.out.println("Recover successfully.");
throw e1;
}
CommandOutputHelper.ADD_LDAP_OUTPUT.printSuccess();
}
} catch (CliRestException e) {
CommandOutputHelper.ADD_LDAP_OUTPUT.printFailure(e);
} catch (ValidationException e) {
handleValidationErrors(e, CommandOutputHelper.ADD_LDAP_OUTPUT);
}
}
private boolean handleUntrustedCertificate(UntrustedCertificateException e,
CommandOutputHelper commandOutputHelper,
Runnable runnable) {
commandOutputHelper.printWarning(e.getMessage());
TlsHelper.presentUserWithCert(e.getCertInfo(), System.out);
List<String> warningList = new ArrayList<>();
warningList.add("The LDAP server's certificate is not trusted yet!!");
boolean userConfirmed = commandOutputHelper.promptWarning(
warningList, false, "Do you want to trust it now(yes/no)?");
if (userConfirmed) {
runnable.run();
} else {
commandOutputHelper.printFailure("The server certificate is not trusted, so the command will stop.");
}
return userConfirmed;
}
private void handleValidationErrors(ValidationException validationEx, CommandOutputHelper outputHelper) {
outputHelper.printFailure(validationEx);
ValidationErrorsStringBuilder stringBuilder = new ValidationErrorsStringBuilder();
System.out.println(stringBuilder.toString(validationEx.getErrors()));
}
private UserMgmtServer parseUserMgmtServer(String cfgFilePath, CommandOutputHelper MODIFY_LDAP_OUTPUT) {
ObjectMapper objectMapper = new ObjectMapper();
FileReader fr = null;
try {
fr = new FileReader(cfgFilePath);
return objectMapper.readValue(new BufferedReader(fr), UserMgmtServer.class);
} catch (FileNotFoundException e) {
MODIFY_LDAP_OUTPUT.printFailure("File " + cfgFilePath + " not found.");
} catch (JsonMappingException | JsonParseException e) {
MODIFY_LDAP_OUTPUT.printFailure("Failed to parse file " + cfgFilePath);
} catch (IOException e) {
MODIFY_LDAP_OUTPUT.printFailure("IO error on reading file " + cfgFilePath);
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
//nothing to do
}
}
}
return null;
}
}