All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.sdk.cloudplatform.connectivity.ScpNeoDestination Maven / Gradle / Ivy

Go to download

Implementation of the Cloud platform abstraction for general-purpose connectivity on the SAP Cloud Platform (Cloud Foundry).

The newest version!
/*
 * Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved.
 */

package com.sap.cloud.sdk.cloudplatform.connectivity;

import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.slf4j.Logger;

import com.google.common.base.Strings;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import com.sap.cloud.sdk.cloudplatform.CloudPlatform;
import com.sap.cloud.sdk.cloudplatform.CloudPlatformAccessor;
import com.sap.cloud.sdk.cloudplatform.ScpNeoCloudPlatform;
import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException;
import com.sap.cloud.sdk.cloudplatform.exception.CloudPlatformException;
import com.sap.cloud.sdk.cloudplatform.exception.ShouldNotHappenException;
import com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory;
import com.sap.cloud.sdk.cloudplatform.security.BasicCredentials;
import com.sap.cloud.sdk.cloudplatform.tenant.ScpNeoTenant;
import com.sap.cloud.sdk.cloudplatform.tenant.Tenant;
import com.sap.cloud.sdk.cloudplatform.tenant.TenantAccessor;
import com.sap.core.connectivity.api.configuration.DestinationConfiguration;

import lombok.Getter;

/**
 * Destination used with the Neo platform.
 *
 * @see ScpNeoGenericDestination
 * @see ScpNeoRfcDestination
 */
public class ScpNeoDestination extends AbstractDestination
{
    private static final Logger logger = CloudLoggerFactory.getLogger(ScpNeoDestination.class);

    private static final int DEFAULT_HTTPS_PORT = 443;

    private static final String SAP_CONNECTIVITY_CONSUMER_ACCOUNT = "SAP-Connectivity-ConsumerAccount";
    private static final String SAP_CONNECTIVITY_SCC_LOCATION_ID_HEADER = "SAP-Connectivity-SCC-Location_ID";

    @Getter
    @Nullable
    private final DestinationConfiguration destinationConfiguration;

    @Nullable
    private final String cloudConnectorLocationId;

    /**
     * Creates a destination to be used on SAP Cloud Platform Neo.
     *
     * @param destinationConfiguration
     *            The destination configuration as received by the Neo container.
     * @param name
     *            The name of the destination.
     * @param description
     *            A description of this destination.
     * @param uri
     *            The uri of this destination.
     * @param authenticationType
     *            The {@code AuthenticationType} of this destination.
     * @param basicCredentials
     *            The credentials to be used if {@code authenticationType} is set to {@code BASIC_AUTHENTICATION}.
     * @param proxyType
     *            The type of proxy to be used for this destination.
     * @param proxyConfiguration
     *            The configuration of the proxy to be used (if given).
     * @param isTrustingAllCertificates
     *            Flag indicating whether all certificates should be accepted when communicating with the destination.
     * @param trustStoreLocation
     *            The name of the trust store to search for in the {@code destinationConfiguration}.
     * @param trustStorePassword
     *            The password to access the trust store.
     * @param keyStoreLocation
     *            The name of the key store to search for in the {@code destinationConfiguration}.
     * @param keyStorePassword
     *            The password to access the key store.
     * @param cloudConnectorLocationId
     *            The id to be used when communicating in {@code ON_PREMISE} {@code proxyType} with an on-premise
     *            system.
     * @param propertiesByName
     *            A map containing all additional properties.
     */
    public ScpNeoDestination(
        @Nullable final DestinationConfiguration destinationConfiguration,
        @Nonnull final String name,
        @Nullable final String description,
        @Nonnull final URI uri,
        @Nonnull final AuthenticationType authenticationType,
        @Nullable final BasicCredentials basicCredentials,
        @Nonnull final ProxyType proxyType,
        @Nullable final ProxyConfiguration proxyConfiguration,
        final boolean isTrustingAllCertificates,
        @Nullable final String trustStoreLocation,
        @Nullable final String trustStorePassword,
        @Nullable final String keyStoreLocation,
        @Nullable final String keyStorePassword,
        @Nullable final String cloudConnectorLocationId,
        @Nonnull final Map propertiesByName )
    {
        this(
            destinationConfiguration,
            name,
            description,
            uri.toString(),
            authenticationType,
            basicCredentials,
            proxyType,
            proxyConfiguration,
            isTrustingAllCertificates,
            trustStoreLocation,
            trustStorePassword,
            keyStoreLocation,
            keyStorePassword,
            cloudConnectorLocationId,
            propertiesByName);
    }

    /**
     * Creates a destination to be used on SAP Cloud Platform Neo.
     *
     * @param destinationConfiguration
     *            The destination configuration as received by the Neo container.
     * @param name
     *            The name of the destination.
     * @param description
     *            A description of this destination.
     * @param uri
     *            The uri of this destination.
     * @param authenticationType
     *            The {@code AuthenticationType} of this destination.
     * @param basicCredentials
     *            The credentials to be used if {@code authenticationType} is set to {@code BASIC_AUTHENTICATION}.
     * @param proxyType
     *            The type of proxy to be used for this destination.
     * @param proxyConfiguration
     *            The configuration of the proxy to be used (if given).
     * @param isTrustingAllCertificates
     *            Flag indicating whether all certificates should be accepted when communicating with the destination.
     * @param trustStoreLocation
     *            The name of the trust store to search for in the {@code destinationConfiguration}.
     * @param trustStorePassword
     *            The password to access the trust store.
     * @param keyStoreLocation
     *            The name of the key store to search for in the {@code destinationConfiguration}.
     * @param keyStorePassword
     *            The password to access the key store.
     * @param cloudConnectorLocationId
     *            The id to be used when communicating in {@code ON_PREMISE} {@code proxyType} with an on-premise
     *            system.
     * @param propertiesByName
     *            A map containing all additional properties.
     */
    public ScpNeoDestination(
        @Nullable final DestinationConfiguration destinationConfiguration,
        @Nonnull final String name,
        @Nullable final String description,
        @Nonnull final String uri,
        @Nonnull final AuthenticationType authenticationType,
        @Nullable final BasicCredentials basicCredentials,
        @Nonnull final ProxyType proxyType,
        @Nullable final ProxyConfiguration proxyConfiguration,
        final boolean isTrustingAllCertificates,
        @Nullable final String trustStoreLocation,
        @Nullable final String trustStorePassword,
        @Nullable final String keyStoreLocation,
        @Nullable final String keyStorePassword,
        @Nullable final String cloudConnectorLocationId,
        @Nonnull final Map propertiesByName )
    {
        super(
            name,
            description,
            uri,
            authenticationType,
            basicCredentials,
            proxyType,
            proxyConfiguration,
            isTrustingAllCertificates,
            trustStoreLocation,
            trustStorePassword,
            keyStoreLocation,
            keyStorePassword,
            propertiesByName);

        this.destinationConfiguration = destinationConfiguration;
        this.cloudConnectorLocationId = cloudConnectorLocationId;
    }

    /**
     * Creates a mocked {@link ScpNeoDestination} returning an empty destination name.
     * 

* This no-arguments constructor is required to ensure compatibility with mocking frameworks such as Mockito. */ private ScpNeoDestination() { this( null, "", null, URI.create(""), AuthenticationType.NO_AUTHENTICATION, null, ProxyType.INTERNET, null, false, null, null, null, null, null, Collections.emptyMap()); } /** * Getter for the location identifier used by the SAP Cloud Connector. * * @return The location identifier. */ @Nonnull public Optional getCloudConnectorLocationId() { return Optional.ofNullable(cloudConnectorLocationId); } @Nonnull @Override public Optional getTrustStore() { if( destinationConfiguration == null ) { return Optional.empty(); } return Optional.ofNullable(destinationConfiguration.getTrustStore()); } @Nonnull @Override public Optional getKeyStore() { if( destinationConfiguration == null ) { return Optional.empty(); } return Optional.ofNullable(destinationConfiguration.getKeyStore()); } private ProxyConfiguration getOnPremiseProxyConfiguration() throws DestinationAccessException { final CloudPlatform cloudPlatform = CloudPlatformAccessor.getCloudPlatform(); if( !(cloudPlatform instanceof ScpNeoCloudPlatform) ) { throw new ShouldNotHappenException( "The current Cloud platform is not an instance of " + ScpNeoCloudPlatform.class.getSimpleName() + ". Please make sure to specify a dependency to com.sap.cloud.s4hana.cloudplatform:core-scp-neo."); } final ScpNeoCloudPlatform scpNeoCloudPlatform = (ScpNeoCloudPlatform) cloudPlatform; try { final String onPremiseProxyHost = scpNeoCloudPlatform.getOnPremiseProxyHost(); final int onPremiseProxyPort = scpNeoCloudPlatform.getOnPremiseProxyPort(); final URI uri = new URI("http://" + onPremiseProxyHost + ":" + onPremiseProxyPort); final ProxyConfiguration proxyConfiguration = new ProxyConfiguration(uri); if( logger.isDebugEnabled() ) { logger.debug("Using on-premise proxy configuration: " + uri + "."); } return proxyConfiguration; } catch( final CloudPlatformException e ) { throw new DestinationAccessException("Failed to get on-premise proxy host or port.", e); } catch( final URISyntaxException e ) { throw new DestinationAccessException("Invalid on-premise proxy host or port.", e); } } @Nonnull @Override public Optional getProxyConfiguration() throws DestinationAccessException { if( getProxyType() == ProxyType.ON_PREMISE ) { return Optional.of(getOnPremiseProxyConfiguration()); } else { return Optional.ofNullable(proxyConfiguration); } } private Collection

getAuthenticationHeaders( @Nullable final URI requestUri ) throws DestinationAccessException { try { return new GetAuthHeadersCommand(this, requestUri).execute(); } catch( final HystrixRuntimeException | HystrixBadRequestException | IllegalStateException e ) { throw new DestinationAccessException( "Failed to get the request headers for destination '" + getName() + "' (request URI: " + requestUri + ").", e); } } @Nullable private String getCurrentAccountId() { final Optional currentTenant = TenantAccessor.getCurrentTenantIfAvailable(); if( !currentTenant.isPresent() ) { if( logger.isDebugEnabled() ) { logger.debug( "Unable to determine current account identifier: tenant not available. " + "The connectivity header '" + SAP_CONNECTIVITY_CONSUMER_ACCOUNT + "' will be omitted. " + "On-premise connectivity may not work in consumer accounts."); } return null; } final Tenant tenant = currentTenant.get(); if( !(tenant instanceof ScpNeoTenant) ) { throw new ShouldNotHappenException( "The current tenant is not an instance of " + ScpNeoTenant.class.getSimpleName() + ". Please make sure to specify a dependency to com.sap.cloud.s4hana.cloudplatform:tenant-scp-neo."); } return ((ScpNeoTenant) tenant).getTenantContext().getTenant().getAccount().getId(); } private Collection
getOnPremiseProxyHeaders() { final List
headers = new ArrayList<>(); @Nullable final String currentAccountId = getCurrentAccountId(); if( !Strings.isNullOrEmpty(currentAccountId) ) { headers.add(new Header(SAP_CONNECTIVITY_CONSUMER_ACCOUNT, currentAccountId)); } if( !Strings.isNullOrEmpty(cloudConnectorLocationId) ) { headers.add(new Header(SAP_CONNECTIVITY_SCC_LOCATION_ID_HEADER, cloudConnectorLocationId)); if( logger.isDebugEnabled() ) { logger.debug( "Successfully added " + SAP_CONNECTIVITY_SCC_LOCATION_ID_HEADER + " header with location identifier '" + cloudConnectorLocationId + "'."); } } return headers; } @Nonnull @Override public List
getHeaders( @Nullable final URI requestUri ) throws DestinationAccessException { final List
headers = super.getHeaders(requestUri); headers.addAll(getAuthenticationHeaders(requestUri)); if( ProxyType.ON_PREMISE == getProxyType() ) { headers.addAll(getOnPremiseProxyHeaders()); } return headers; } @Nonnull @Override public URI getUri() throws DestinationAccessException { final URI uri = super.getUri(); // for on-premise destinations, convert "https" to "http" while keeping port 443, if necessary if( getProxyType() == ProxyType.ON_PREMISE && "https".equals(uri.getScheme()) ) { if( logger.isWarnEnabled() ) { logger.warn( "Rewriting on-premise destination '" + getName() + "' with URI scheme 'https' to use 'http': " + uri + ". To resolve this warning, make sure to use 'http' for on-premise destinations."); } // keep the default HTTPS port if no port was specified final int port = uri.getPort() < 0 ? DEFAULT_HTTPS_PORT : uri.getPort(); try { return new URI( "http", uri.getUserInfo(), uri.getHost(), port, uri.getPath(), uri.getQuery(), uri.getFragment()); } catch( final URISyntaxException e ) { throw new DestinationAccessException("Invalid destination URI.", e); } } return uri; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy