I am trying to make a HTTPs call using RESTAssured. I am using a .pfx certficate. But the call is ending in a handshake failure. Below is the code I am using.
FileInputStream instream1=null;
FileInputStream instream2=null;
KeyStore trustStore=null;
KeyStore keyStore=null;
instream1 = new FileInputStream(new File(keystore));
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(instream1, keystorepwd.toCharArray());
instream2 = new FileInputStream (new File(truststore));
trustStore = KeyStore.getInstance("jks");
trustStore.load(instream2, truststorepwd.toCharArray());
X509HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
org.apache.http.conn.ssl.SSLSocketFactory lSchemeSocketFactory=null;
lSchemeSocketFactory = new org.apache.http.conn.ssl.SSLSocketFactory(keyStore, keystorepwd);
lSchemeSocketFactory.setHostnameVerifier(hostnameVerifier);
RestAssured.config = RestAssured.config().sslConfig(new SSLConfig().with().sslSocketFactory(lSchemeSocketFactory).and().allowAllHostnames());
response = RestAssured.given()
.relaxedHTTPSValidation()
.contentType("application/json")
.header("Accept-Encoding","gzip,deflate")
.body(\\body)
.post()
.then().log().all()
.assertThat().statusCode(201)
.assertThat().extract().response();
I was able to resolve the issue with a small modification.
FileInputStream instream1=null;
KeyStore keyStore=null;
instream1 = new FileInputStream(new File(keystore));
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(instream1, keystorepwd.toCharArray());
X509HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
org.apache.http.conn.ssl.SSLSocketFactory lSchemeSocketFactory=null;
lSchemeSocketFactory = new org.apache.http.conn.ssl.SSLSocketFactory(keyStore, keystorepwd);
lSchemeSocketFactory.setHostnameVerifier(hostnameVerifier);
RestAssured.config = RestAssured.config().sslConfig(new SSLConfig().with().sslSocketFactory(lSchemeSocketFactory).and().allowAllHostnames());
response = RestAssured.given()
.relaxedHTTPSValidation()
.contentType("application/json")
.header("Accept-Encoding","gzip,deflate")
.body(\\body)
.post()
.then().log().all()
.assertThat().statusCode(201)
.assertThat().extract().response();
Related
Using protocol Http2 and trying to disable the hostname verification
But this didn't work for me
return HttpClient.create()
.secure(sslContextSpec ->
sslContextSpec.sslContext(createSslContext(pcfSmpcClientProperties))
.handlerConfigurator(
(handler)->{
SSLEngine engine = handler.engine();
//engine.setNeedClientAuth(true);
SSLParameters params = new SSLParameters();
List<SNIMatcher> matchers = new LinkedList<>();
SNIMatcher matcher = new SNIMatcher(0) {
#Override
public boolean matches(SNIServerName serverName) {
return true;
}
};
matchers.add(matcher);
params.setSNIMatchers(matchers);
engine.setSSLParameters(params);
}
)
)
.wiretap(true)
.protocol(HttpProtocol.H2)
.compress(true)
.followRedirect(true)
You are trying to supress the Server name indicator [SNI] and what you are lookin is to skip HostName verification.
In-order to achieve it you can set the endpointIdentificationAlgorithm either null or "", based on your JDK version.
SSLEngine engine = handler.engine();
SSLParameters params = new SSLParameters();
params.setEndpointIdentificationAlgorithm("");
engine.setSSLParameters(params);
If elasticsearch runs on single mode, I can easily establish the RestHighLevel connection with this line of code:
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
But if my elastic cluster has 3 machines, e.g., "host1", "host2", "host3", how to create the rest high level client in cluster mode ?
Thanks
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("host1", 9200, "http"),
new HttpHost("host2", 9200, "http"),
new HttpHost("host2", 9200, "http")
)
);
As the doc it looks like you were referencing states, RestClient.builder accepts an array of HttpHosts to connect to. The client (which under the hood is the ES low-level REST client) will round-robin requests to these hosts. See also the Javadoc.
As per the Elasticsearch docs you can pass multiple Elasticsearch hosts in RestClient.builder().
The better solution is to load the Elasticsearch hosts from configuration(application.conf in case of Scala-based application) instead of hardcoding it in the codebase.
Here is the Scala-based solution using Java Varargs(:_*).
application.conf
es_hosts = ["x.x.x.x","x.x.x.x","x.x.x.x"] // You can even use service-name/service-discovery
es_port = 9200
es_scheme = "http"
Code snippet
import collection.JavaConverters._
import com.typesafe.config.ConfigFactory
import org.apache.http.HttpHost
import org.elasticsearch.client.{RestClient, RestHighLevelClient}
val config = ConfigFactory.load()
val port = config.getInt(ES_PORT)
val scheme = config.getString(ES_SCHEME)
val es_hosts = config.getStringList(ES_HOSTS).asScala
val httpHosts = es_hosts.map(host => new HttpHost(host, port, scheme))
val low_level_client = RestClient.builder(httpHosts:_*)
val high_level_client: RestHighLevelClient = new RestHighLevelClient(low_level_client)
To create High level REST client using multiple hosts, you can do something like following:
String[] esHosts = new String[]{"node1-example.com:9200", "node2-example.com:9200",
"node3-example.com:9200"};
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(esHosts)
.build();
RestHighLevelClient restClient = RestClients.create(clientConfiguration).rest();
// Hostnames used for building client can be verified as following
List<Node> nodes = restClient.getLowLevelClient().getNodes();
nodes.forEach(node -> System.out.println(node.toString()));
References:
Docs for High Level REST Client
Source code for ClientConfigurationBuilder
I am creating my elastic REST client with below steps:
RestHighLevelClient client=null;
List<HttpHost> hostList = new ArrayList<>();
for (String host : hosts) {
String[] hostDetails = host.split("\\:");hostList.add(new
HttpHost(hostDetails[0],Integer.parseInt(hostDetails[1]),https));
}
try(RestHighLevelClient client1 = new RestHighLevelClient(
RestClient.builder(hostList.toArray(new
HttpHost[hostList.size()]))
.setHttpClientConfigCallback(
httpClientBuilder ->
// to do this only if auth is enabled
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))))
{
client = client1;
}
} catch (IOException e) {
log.error("exception occurred while setting elastic client");
}
Getting Error - javax.net.ssl.SSLHandshakeException: Server chose TLSv1, but that protocol version is not enabled or not supported by the client when making a call to a secured webservice.
Appended the following option to the JAVA_OPTIONS variable in the mydomain\bin\ setDomainEnv.cmd as advised in the oracle site but same issue.
-Dweblogic.security.SSL.protocolVersion=TLS1
Java client code :
File pKeyFile = new File("C:\\myJKS.jks");
if (pKeyFile.exists() && !pKeyFile.isDirectory()) {
logger.debug("JKS file exists, and it is a file");
}
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(pKeyFile.toString()),
pKeyPassword.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
**SSLContext context = SSLContext.getInstance("TLSv1.1");**
context.init(keyManagerFactory.getKeyManagers(), null,
new SecureRandom());
sockFact = context.getSocketFactory();
if(sockFact == null){
logger.debug("SocketFactory is null");
throw new NullPointerException("socketFactory == null");
}
Client Env - JDK version: 7, Application server:Weblogic.
Trying to make it work from couple of days, but no luck.
We are using Identity Server4 with EntityFrameworkCore and we have deployed our .NET Core application as a lambda function using aws toolkit ("https://aws.amazon.com/blogs/developer/preview-of-the-aws-toolkit-for-visual-studio-2017/"). So how we can replace AddDeveloperSigningCredential on aws serverless lambda environment?
Here is our ConfigurationServerices method:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
string connectionString = Configuration.GetConnectionString("IdentityServer");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
}) // this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
// options.EnableTokenCleanup = true;
// options.TokenCleanupInterval = 30;
});
// Add S3 to the ASP.NET Core dependency injection framework.
services.AddAWSService<Amazon.S3.IAmazonS3>();
}
This is some example code that loads certs from the certificate store. If this is unavailable to you then you just need to serialise and persist the certificate(s) you need some other way but that ultimately yields a valid X509Certificate2 instance that you can pass into X509SecurityKey.
private static void ConfigureSigningCerts(IServiceCollection services)
{
var keys = new List<SecurityKey>();
var name = "MyCertName";
//The one that expires last at the top
var certs = X509.LocalMachine.My.SubjectDistinguishedName.Find("CN=" + name, false)
.Where(o => DateTime.UtcNow >= o.NotBefore)
.OrderByDescending(o => o.NotAfter);
if (!certs.Any()) throw new Exception("No valid certificates could be found.");
//Get first (in desc order of expiry) th
var signingCert = certs.FirstOrDefault();
if (signingCert == null) throw new InvalidOperationException("No valid signing certificate could be found.");
var signingCredential = new SigningCredentials(new X509SecurityKey(signingCert), "RS256");
services.AddSingleton<ISigningCredentialStore>(new DefaultSigningCredentialsStore(signingCredential));
foreach (var cert in certs)
{
var validationCredential = new SigningCredentials(new X509SecurityKey(cert), "RS256");
keys.Add(validationCredential.Key);
}
services.AddSingleton<IValidationKeysStore>(new DefaultValidationKeysStore(keys));
}
The constructor for X509Certificate2 can take a raw byte[] or a file path so you've got plenty of options when it comes to packaging and distributing the signing/validation certs.
To create a self signed certificate on windows you can use the command:
makecert -r -pe -n "CN=MyCertName" -b 01/01/2015 -e 01/01/2039 -eku 1.3.6.1.5.5.7.3.3 -sky signature -a sha256 -len 2048 mycert.cer
That creates a certificate named MyCertName in a file called mycert.cer.
Full docs for the tool here: https://msdn.microsoft.com/en-us/library/bfsktky3(VS.100).aspx
Using UIL version 1.8.0 to load a twitter profile image url:
http://api.twitter.com/1/users/profile_image/smashingmag.jpg?size=bigger
with disc and memory cache. The images are failing to load and storing the html that comes along with the 302 redirect in the disc cache file. The images never load or decode successfully (the onLoadingFailed method of my SimpleImageLoadingListener gets called for every twitter profile image url). Can anyone load a simple twitter image url with UIL?
Here is the content of my cache file for that url:
cat /mnt/sdcard/MyCache/CacheDir/1183818163
<html><body>You are being redirected.</body></html>
Here is my configuration:
File cacheDir = StorageUtils.getOwnCacheDirectory(FrequencyApplication.getContext(), "MyCache/CacheDir");
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(FrequencyApplication.getContext())
.memoryCacheExtraOptions(480, 800)
.threadPoolSize(20)
.threadPriority(Thread.MIN_PRIORITY)
.offOutOfMemoryHandling()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
.discCache(new TotalSizeLimitedDiscCache(cacheDir, 30 * 1024 * 1024))
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.imageDownloader(new BaseImageDownloader(MyApplication.getContext(), 20 * 1000, 30 * 1000))
.tasksProcessingOrder(QueueProcessingType.FIFO)
.defaultDisplayImageOptions(defaultOptions)
.build();
ImageLoader.getInstance().init(config);
It seems HttpURLConnection can't handle redirect from HTTP to HTTPS automatically (link). I'll fix it in next lib version.
Fix for now - extend BaseImageDownloader and set it into configuration:
public class MyImageDownloader implements BaseImageDownloader {
#Override
protected InputStream getStreamFromNetwork(URI imageUri, Object extra) throws IOException {
HttpURLConnection conn = (HttpURLConnection) imageUri.toURL().openConnection();
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
conn.connect();
while (conn.getResponseCode() == 302) { // >=300 && < 400
String redirectUrl = conn.getHeaderField("Location");
conn = (HttpURLConnection) new URL(redirectUrl).openConnection();
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
conn.connect();
}
return new FlushedInputStream(conn.getInputStream(), BUFFER_SIZE);
}
}