package com.sequenceiq.cloudbreak.service.stack.connector.adapter; import static com.sequenceiq.cloudbreak.cloud.model.CloudCredential.SMART_SENSE_ID; import java.io.IOException; import java.util.Map; import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.google.api.client.repackaged.com.google.common.base.Strings; import com.sequenceiq.cloudbreak.cloud.context.CloudContext; import com.sequenceiq.cloudbreak.cloud.event.credential.CredentialVerificationRequest; import com.sequenceiq.cloudbreak.cloud.event.credential.CredentialVerificationResult; import com.sequenceiq.cloudbreak.cloud.event.credential.InteractiveLoginRequest; import com.sequenceiq.cloudbreak.cloud.event.credential.InteractiveLoginResult; import com.sequenceiq.cloudbreak.cloud.event.model.EventStatus; import com.sequenceiq.cloudbreak.cloud.model.CloudCredential; import com.sequenceiq.cloudbreak.cloud.model.CredentialStatus; import com.sequenceiq.cloudbreak.cloud.model.ExtendedCloudCredential; import com.sequenceiq.cloudbreak.controller.BadRequestException; import com.sequenceiq.cloudbreak.converter.spi.CredentialToCloudCredentialConverter; import com.sequenceiq.cloudbreak.converter.spi.CredentialToExtendedCloudCredentialConverter; import com.sequenceiq.cloudbreak.domain.Credential; import com.sequenceiq.cloudbreak.domain.json.Json; import com.sequenceiq.cloudbreak.service.credential.OpenSshPublicKeyValidator; import com.sequenceiq.cloudbreak.service.stack.connector.OperationException; import reactor.bus.Event; import reactor.bus.EventBus; @Component public class ServiceProviderCredentialAdapter { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceProviderCredentialAdapter.class); @Inject private EventBus eventBus; @Inject private OpenSshPublicKeyValidator rsaPublicKeyValidator; @Inject private CredentialToCloudCredentialConverter credentialConverter; @Inject private CredentialToExtendedCloudCredentialConverter extendedCloudCredentialConverter; public Credential init(Credential credential) { if (!credential.passwordAuthenticationRequired() && !Strings.isNullOrEmpty(credential.getPublicKey())) { rsaPublicKeyValidator.validate(credential.getPublicKey()); } CloudContext cloudContext = new CloudContext(credential.getId(), credential.getName(), credential.cloudPlatform(), credential.getOwner()); CloudCredential cloudCredential = credentialConverter.convert(credential); CredentialVerificationRequest request = new CredentialVerificationRequest(cloudContext, cloudCredential); LOGGER.info("Triggering event: {}", request); eventBus.notify(request.selector(), Event.wrap(request)); try { CredentialVerificationResult res = request.await(); String message = "Failed to verify the credential: "; LOGGER.info("Result: {}", res); if (res.getStatus() != EventStatus.OK) { LOGGER.error(message, res.getErrorDetails()); throw new BadRequestException(message + res.getErrorDetails(), res.getErrorDetails()); } if (CredentialStatus.FAILED.equals(res.getCloudCredentialStatus().getStatus())) { throw new BadRequestException(message + res.getCloudCredentialStatus().getStatusReason(), res.getCloudCredentialStatus().getException()); } CloudCredential cloudCredentialResponse = res.getCloudCredentialStatus().getCloudCredential(); mergeSmartSenseAttributeIfExists(credential, cloudCredentialResponse); } catch (InterruptedException e) { LOGGER.error("Error while executing credential verification", e); throw new OperationException(e); } return credential; } public Map<String, String> interactiveLogin(Credential credential) { CloudContext cloudContext = new CloudContext(credential.getId(), credential.getName(), credential.cloudPlatform(), credential.getOwner()); ExtendedCloudCredential cloudCredential = extendedCloudCredentialConverter.convert(credential); InteractiveLoginRequest request = new InteractiveLoginRequest(cloudContext, cloudCredential); LOGGER.info("Triggering event: {}", request); eventBus.notify(request.selector(), Event.wrap(request)); try { InteractiveLoginResult res = request.await(); String message = "Interactive login Failed: "; LOGGER.info("Result: {}", res); if (res.getStatus() != EventStatus.OK) { LOGGER.error(message, res.getErrorDetails()); throw new BadRequestException(message + res.getErrorDetails(), res.getErrorDetails()); } return res.getParameters(); } catch (InterruptedException e) { LOGGER.error("Error while executing credential verification", e); throw new OperationException(e); } } public Credential update(Credential credential) { return credential; } private void mergeSmartSenseAttributeIfExists(Credential credential, CloudCredential cloudCredentialResponse) { String smartSenseId = String.valueOf(cloudCredentialResponse.getParameters().get(SMART_SENSE_ID)); if (StringUtils.isNoneEmpty(smartSenseId)) { try { Json attributes = credential.getAttributes(); Map<String, Object> newAttributes = attributes.getMap(); newAttributes.put(SMART_SENSE_ID, smartSenseId); credential.setAttributes(new Json(newAttributes)); } catch (IOException e) { LOGGER.error("SmartSense id could not be added to the credential as attribute.", e); } } } }