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;
/**
* 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;
}
/**
* @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();
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();
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
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);
}
}
}
}
- 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;