Update docker image to fix CSIT failure
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / vnfm / CbamTokenProvider.java
index e49c572..c4a6645 100644 (file)
 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.io.BaseEncoding;
 import com.google.gson.Gson;
 import com.google.gson.annotations.SerializedName;
+import java.io.IOException;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocketFactory;
 import okhttp3.*;
-import org.apache.http.conn.ssl.DefaultHostnameVerifier;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider;
-import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.StoreLoader;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.GenericExternalSystemInfoProvider;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.VnfmCredentials;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.VnfmUrls;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions;
-import org.onap.vnfmdriver.model.VnfmInfo;
 import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
-
-import javax.net.ssl.*;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.security.*;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.security.spec.InvalidKeySpecException;
-import java.util.Set;
 
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.buildFatalFailure;
 import static org.slf4j.LoggerFactory.getLogger;
 import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
 import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
@@ -48,27 +37,18 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL
 /**
  * Responsible for providing a token to access CBAM APIs
  */
-@Component
-public class CbamTokenProvider {
+//even if the value for grant type an user password is the same they do not mean the same thing
+//the duplication of this is intentional
+@SuppressWarnings("squid:S1192")
+public class CbamTokenProvider extends CbamSecurityProvider {
     public static final int MAX_RETRY_COUNT = 5;
-    private static final String CBAM_TOKEN_PATH = "/realms/cbam/protocol/openid-connect/token";
+    public static final String GRANT_TYPE = "password";
+    public static final String CLIENT_SECRET = "password";
+    private static final String CBAM_TOKEN_URL = "realms/cbam/protocol/openid-connect/token";
     private static Logger logger = getLogger(CbamTokenProvider.class);
     private final VnfmInfoProvider vnfmInfoProvider;
-    @Value("${cbamKeyCloakBaseUrl}")
-    private String cbamKeyCloakBaseUrl;
-    @Value("${cbamUsername}")
-    private String username;
-    @Value("${cbamPassword}")
-    private String password;
-    @Value("${trustedCertificates}")
-    private String trustedCertificates;
-    @Value("${skipCertificateVerification}")
-    private boolean skipCertificateVerification;
-    @Value("${skipHostnameVerification}")
-    private boolean skipHostnameVerification;
     private volatile CurrentToken token;
 
-    @Autowired
     CbamTokenProvider(VnfmInfoProvider vnfmInfoProvider) {
         this.vnfmInfoProvider = vnfmInfoProvider;
     }
@@ -76,12 +56,11 @@ public class CbamTokenProvider {
     /**
      * @return the token to access CBAM APIs (ex. 123456)
      */
-    public String getToken(String vnfmId) {
-        VnfmInfo vnfmInfo = vnfmInfoProvider.getVnfmInfo(vnfmId);
-        return getToken(vnfmInfo.getUserName(), vnfmInfo.getPassword());
+    public Interceptor getToken(String vnfmId) {
+        return new OauthInterceptor(getTokenInternal(vnfmId));
     }
 
-    private String getToken(String clientId, String clientSecret) {
+    private String getTokenInternal(String vnfmId) {
         logger.trace("Requesting token for accessing CBAM API");
         synchronized (this) {
             long now = SystemFunctions.systemFunctions().currentTimeMillis();
@@ -89,26 +68,28 @@ public class CbamTokenProvider {
                 if (token == null) {
                     logger.debug("No token: getting first token");
                 } else {
-                    logger.debug("Token expired " + (now - token.refreshAfter) + " ms ago");
+                    logger.debug("Token expired {} ms ago", (now - token.refreshAfter));
                 }
-                refresh(clientId, clientSecret);
+                refresh(vnfmId);
             } else {
-                logger.debug("Token will expire in " + (now - token.refreshAfter) + " ms");
+                logger.debug("Token will expire in {} ms", (now - token.refreshAfter));
             }
         }
         return token.token.accessToken;
     }
 
-    ;
+    private void refresh(String vnfmId) {
+        VnfmUrls vnfmUrls = GenericExternalSystemInfoProvider.convert(vnfmInfoProvider.getVnfmInfo(vnfmId));
+        VnfmCredentials vnfmCredentials = GenericExternalSystemInfoProvider.convertToCredentials(vnfmInfoProvider.getVnfmInfo(vnfmId));
 
-    private void refresh(String clientId, String clientSecret) {
         FormBody body = new FormBody.Builder()
-                .add("grant_type", "password")
-                .add("client_id", clientId)
-                .add("client_secret", clientSecret)
-                .add("username", username)
-                .add("password", password).build();
-        Request request = new Request.Builder().url(cbamKeyCloakBaseUrl + CBAM_TOKEN_PATH).addHeader(CONTENT_TYPE, APPLICATION_FORM_URLENCODED_VALUE).post(body).build();
+                .add("grant_type", GRANT_TYPE)
+                .add("client_id", vnfmCredentials.getClientId())
+                .add("client_secret", vnfmCredentials.getClientSecret())
+                .add("username", vnfmCredentials.getUsername())
+                .add(CLIENT_SECRET, vnfmCredentials.getPassword()).build();
+        String cbamKeyCloakBaseUrl = vnfmUrls.getAuthUrl();
+        Request request = new Request.Builder().url(cbamKeyCloakBaseUrl + CBAM_TOKEN_URL).addHeader(CONTENT_TYPE, APPLICATION_FORM_URLENCODED_VALUE).post(body).build();
         OkHttpClient.Builder builder = new OkHttpClient.Builder();
         SSLSocketFactory sslSocketFac = buildSSLSocketFactory();
         HostnameVerifier hostnameVerifier = buildHostnameVerifier();
@@ -124,15 +105,14 @@ public class CbamTokenProvider {
                     token = new CurrentToken(tokenResponse, getTokenRefreshTime(tokenResponse));
                     return;
                 } else {
-                    throw new RuntimeException();
+                    throw buildFatalFailure(logger, "Bad response from CBAM KeyStone");
                 }
             } catch (Exception e) {
                 lastException = e;
                 logger.warn("Unable to get token to access CBAM API (" + (i + 1) + "/" + MAX_RETRY_COUNT + ")", e);
             }
         }
-        logger.error("Unable to get token to access CBAM API (giving up retries)", lastException);
-        throw new RuntimeException(lastException);
+        throw buildFatalFailure(logger, "Unable to get token to access CBAM API (giving up retries)", lastException);
     }
 
     @VisibleForTesting
@@ -151,51 +131,20 @@ public class CbamTokenProvider {
         return SystemFunctions.systemFunctions().currentTimeMillis() + token.expiresIn * (1000 / 2);
     }
 
-    private HostnameVerifier buildHostnameVerifier() {
-        if (skipHostnameVerification) {
-            return new HostnameVerifier() {
-                @Override
-                public boolean verify(String hostname, SSLSession session) {
-                    return true;
-                }
-            };
-        } else {
-            return new DefaultHostnameVerifier();
-        }
-    }
+    private static class OauthInterceptor implements Interceptor {
+        private final String token;
 
-    @VisibleForTesting
-    SSLSocketFactory buildSSLSocketFactory() {
-        try {
-            TrustManager[] trustManagers = buildTrustManager();
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(null, trustManagers, new SecureRandom());
-            return sslContext.getSocketFactory();
-        } catch (GeneralSecurityException e) {
-            logger.error("Unable to create SSL socket factory", e);
-            throw new RuntimeException(e);
+        OauthInterceptor(String token) {
+            this.token = token;
         }
-    }
-
-    @VisibleForTesting
-    TrustManager[] buildTrustManager() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, CertificateException {
-        if (skipCertificateVerification) {
-            return new TrustManager[]{new AllTrustedTrustManager()};
-        } else {
-            if (StringUtils.isEmpty(trustedCertificates)) {
-                throw new IllegalArgumentException("If the skipCertificateVerification is set to false (default) the trustedCertificates can not be empty");
-            }
-            Set<String> trustedPems;
-            try {
-                trustedPems = StoreLoader.getCertifacates(new String(BaseEncoding.base64().decode(trustedCertificates), StandardCharsets.UTF_8));
-            } catch (Exception e) {
-                throw new RuntimeException("The trustedCertificates must be a base64 encoded collection of PEM certificates", e);
-            }
-            KeyStore keyStore = StoreLoader.loadStore(Joiner.on("\n").join(trustedPems), "password", "password");
-            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-            trustManagerFactory.init(keyStore);
-            return trustManagerFactory.getTrustManagers();
 
+        @Override
+        public Response intercept(Chain chain) throws IOException {
+            Request request = chain.request();
+            Request.Builder builder = request.newBuilder();
+            builder.addHeader("Authorization", "Bearer " + token);
+            Request request1 = builder.build();
+            return chain.proceed(request1);
         }
     }
 
@@ -209,26 +158,9 @@ public class CbamTokenProvider {
         }
     }
 
-    static class AllTrustedTrustManager implements X509TrustManager {
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-
-        }
-
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
-        }
-
-        @Override
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[0];
-        }
-    }
-
     /**
      * Represents the token received from CBAM
      */
-    //FIXME use authentication swagger client instead
     private static class TokenResponse {
         @SerializedName("access_token")
         String accessToken;