I'm using AWS CA to generate an SSL certificate for ElasticBeanstalk that I'm using in my Flutter app.
Based on the bets practices, I'm trying to pin HTTP client the Root certificate from Amazon Trusted Services
I face 2 issues with the Flutter HTTP client:
Whenever I try to load the certificate it crashes:
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: TlsException: Failure trusting builtin roots (OS Error: BAD_PKCS12_DATA(pkcs8_x509.c:657), errno = 0)
This is the certificate I use (one of five, I add them all):
final _awsRoot1 = _decodePEM("""-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----""");
And this is what I do to decode PEM :
Uint8List _decodePEM(pem) {
for (var s in _startsWith) {
if (pem.startsWith(s)) pem = pem.substring(s.length);
}
for (var s in _endsWith) {
if (pem.endsWith(s)) pem = pem.substring(0, pem.length - s.length);
}
pem = pem.replaceAll('\n', '');
pem = pem.replaceAll('\r', '');
return Uint8List.fromList(base64.decode(pem));
}
And add it via:
void certificatePinningPem(SecurityContext context) {
context.setTrustedCertificatesBytes(_awsRoot1);
context.setTrustedCertificatesBytes(_awsRoot2);
context.setTrustedCertificatesBytes(_awsRoot3);
context.setTrustedCertificatesBytes(_awsRoot4);
context.setTrustedCertificatesBytes(_awsRoot5);
}
I get the same exception when I read DER file :
final aws1 = await rootBundle.load('assets/cer/aws1.cer');
context.setTrustedCertificatesBytes(aws1.buffer.asUint8List());
PEM file from the connection is different
Despite that, when I use badCertificateCallback, pem file from the certificate doesn't match any of those five from repo So how to get Root certificate from connection?
httpClient.badCertificateCallback = (
X509Certificate certificate,
String host,
int port,
) {
print('Bad certificate: ${certificate.pem} for host $host:$port');
return false;
};
Any suggestion on how to properly do certificate pinning in Flutter with AWS Root certificates?
I found a few related threads but they don't really help, i.e. https://github.com/flutter/flutter/issues/39190#issuecomment-693315205
Related
After adding the following adaptive authentication script, if the username is not according to the format I should be getting the custom status message saying, Access Denied, invalid username format. But instead I get the default status message, Something went wrong during the authentication process. Please try signing in again.
function onLoginRequest(context) {
executeStep(1, {
onSuccess: function(context) {
var user = context.currentKnownSubject;
if(user!= null && user.username != null && !user.username.equals('')) {
Log.info("username: " + user.username);
} else {
sendError('',{'status':'AUTHENTICATION USERNAME ERROR', 'statusMsg': 'Access denied, invalid username format.'});
}
}
});
}
In addition, I get the following error in the wso2carbon.log file as well.
TID: [-1234] [authenticationendpoint] [2022-10-05 15:44:12,715] [37951f7d-8240-48d4-ad4f-1d4c8a6a3ec4] ERROR {org.wso2.carbon.identity.application.authentication.endpoint.util.AuthContextAPIClient} - Sending GET request to URL : https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/0b0efc37-819d-4b39-85b2-517126c3c9cb, failed. java.io.IOException: Server returned HTTP response code: 401 for URL: https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/0b0efc37-819d-4b39-85b2-517126c3c9cb
...
org.wso2.carbon.identity.application.authentication.endpoint.util.AuthContextAPIClient.getContextProperties(AuthContextAPIClient.java:70)
at org.apache.jsp.retry_jsp._jspService(retry_jsp.java:194)
...
org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter.doFilter(ContentTypeBasedCachePreventionFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
...
org.wso2.carbon.identity.application.authentication.endpoint.util.filter.AuthenticationEndpointFilter.doFilter(AuthenticationEndpointFilter.java:190)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
...
The <IS_HOME>/repository/conf/deployment.toml configurations for [server] are as follows.
[server]
hostname = "dev.wso2istemp.com"
node_ip = "127.0.0.1"
base_path = "https://$ref{server.hostname}:${carbon.management.port}"
What is the reason for the following issue in the wso2carbon.log and why the custom status message is not shown properly?
When the adaptive authentication script is running, the values are passed to the Identity Server(IS) encrypted. In above case, the encrypted data chunk is passed to the IS,
https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/24e56d99-9494-4989-a3e2-4008b73ebd9b
with the last segment of the URL is being the data chunk. When the server tries to get that data chunk with a GET request, java.io.IOException: Server returned HTTP response code: 401 for URL which is the code for unauthorized is thrown. Since that data chunk is not properly received, the default status message is shown instead of the custom status message. The steps to resolve this are given below.
First clarify whether the dev.wso2istemp.com which you were using is not mapped with the localhost in /etc/hosts file.
Go to <IS_HOME>/repository/conf/deployment.toml file and check for the following configuration [identity.auth_framework.endpoint] and check whether the mutual SSL is set to false via mutual_ssl_manager_enabled=false
If so, enable that by commenting the mutual_ssl_manager_enabled=false, since using mutual SSL is recommended for IS. If you go to the <IS_HOME>/repository/resources/conf/default.json file, you can notice that the default value for mutual_ssl_manager_enabled is true
In a multi-node situation, the above error can occur if the mutual SSL is not enabled, If that does not resolves the issue, then you have to check whether the internal_hostname has been set properly so that the internal API calls are being sent properly.
To do that, if you have not added the following configuration to <IS_HOME>/repository/conf/deployment.toml file, you can check whether it has been properly applied to the <IS_HOME>/repository/conf/identity/identity.xml by checking for <ServerHostName>localhost</ServerHostName>
[server]
internal_hostname="localhost"
If you are using a multi-node deployment, this localhost value should be added to the SAN for the certificate when the certificate is generated (-ext SAN=dns:localhost)
keytool -genkey -alias newcert -keyalg RSA -keysize 2048 -keystore newkeystore.jks -dname "CN=dev.wso2istemp.com, OU=Is,O=Wso2,L=SL,S=WS,C=LK" -storepass mypassword -keypass mypassword -ext SAN=dns:localhost
But if you are using a single node you can add the following configuration to the deployment.toml and check whether it resolves things. (In single node case the internal_hostname should be similar to hostname)
[server]
hostname = "dev.wso2istemp.com"
internal_hostname = "dev.wso2istemp.com"
If that is not working[https://github.com/wso2/product-is/issues/11878] then go to <IS_HOME>/repository/deployment/server/webapps/authenticationendpoint/WEB-INF/web.xml and uncomment the following commented snippet.
<!--context-param>
<param-name>AuthenticationRESTEndpointURL</param-name>
<param-value>https://localhost:9443/api/identity/auth/v1.1/</param-value>
</context-param-->
This might route the internal_hostname being reflected on the request since the internal API calls are blocked when hostname of the server being replaced instead of the internal_hostname for the internal API calls(https://dev.wso2istemp.com/api/identity/auth/v1.1/data/AuthenticationError/24e56d99-9494-4989-a3e2-4008b73ebd9b).
Hi i have a project about connect ESP32 to NATS via MQTT
After I try --insecurity it work normally.
But when I add TLS it doesn't work in my ESP32, i also try with Python it work normally with my self-signed SSL certificate.
I already find solution from here but it not work: https://github.com/espressif/arduino-esp32/issues/5021
My idea code get from here: https://github.com/debsahu/ESP-MQTT-AWS-IoT-Core/blob/master/Arduino/PubSubClient/PubSubClient.ino
Is MQTT TLS in ESP32 not work with self-signed cert or I done something wrong ?
Cert TLS:
"-----BEGIN CERTIFICATE-----\n"
"MIID8TCCAtmgAwIBAgIUfceZXKK1JIqHi57rc98EBmJoy1kwDQYJKoZIhvcNAQEL\n"
"BQAwgYcxCzAJBgNVBAYTAlZOMRAwDgYDVQQIDAd2aWV0bmFtMRAwDgYDVQQHDAd2\n"
"aWV0bmFtMQ4wDAYDVQQKDAVwZWNvbTENMAsGA1UECwwEdGVzdDENMAsGA1UEAwwE\n"
"bXF0dDEmMCQGCSqGSIb3DQEJARYXY3B0cHJpY2UxMjNAb3V0bG9vay5jb20wHhcN\n"
"MjIxMTAzMDgxMDEzWhcNMjMxMTAzMDgxMDEzWjCBhzELMAkGA1UEBhMCVk4xEDAO\n"
"BgNVBAgMB3ZpZXRuYW0xEDAOBgNVBAcMB3ZpZXRuYW0xDjAMBgNVBAoMBXBlY29t\n"
"MQ0wCwYDVQQLDAR0ZXN0MQ0wCwYDVQQDDARtcXR0MSYwJAYJKoZIhvcNAQkBFhdj\n"
"cHRwcmljZTEyM0BvdXRsb29rLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n"
"AQoCggEBALRTuKn8m1QuFJI3THb2rkEiKPHD/cdRs/E1Vb96GIBSy4D/s8vJ2OWd\n"
"GHlbLK557OpAH7JrRg6tVEVVr3293u8imwDIcNyOHlBYWSO/DBKGXsoCbOL1u6Gd\n"
"zAn/G+96eX3RUIHRbBF/rE6DZS5Y1Piq7FwdaReHSZhMPB+UMB4xUEC3pC6CzqFt\n"
"xjudk9zT5VpR60XiJAls3YtYpUu4zRZUw2Sb1ZsPmT555QFYbOcF4XlC82MVi/o3\n"
"M91LJ8DyiOvNWxuioIT2frEyIXaTleug3Ev0ALiu8ug9/v/zTWZWq3KA98HZJcm+\n"
"Hr8dChlMewpMpabEi1e0twlzTPw9QyMCAwEAAaNTMFEwHQYDVR0OBBYEFE3SQ0F5\n"
"yzsBkHUcFp/KucgyGHpWMB8GA1UdIwQYMBaAFE3SQ0F5yzsBkHUcFp/KucgyGHpW\n"
"MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAC+pjnAd9c71DfCv\n"
"RUMvYg93mraaqtoEw22ggtT9AfIZfI+o8L5Nxk5us+9k9IBEP4hi6DHtnFxqfFt8\n"
"YkzNNDMTDvLfg/1INUwg8yBYS9Z2+puoPlPTvaxOJiuz2+DkYV/LnUdTolKPqYrO\n"
"IBIbmwMNz0Bqn1XZ7Mjx9U7p+A2N/87NGl3fo0I0tWBRSGXFZB7IYipgCPQG5Eb+\n"
"ZL9vrgFuNJhAVALvDfwKxCX6VdyNpthAMA7cmra+s0/weZsfQLyU2TtnsIg0uoq0\n"
"L4sTpL6Q7Fr4UpOJrezNx/kuHHxBBKhJtlz4Tcaw/OKu/h2g5jjHFT9yN86KUxSY\n"
"PDH47kk=\n"
"-----END CERTIFICATE-----\n";
// You can use x.509 client certificates if you want
const char *test_client_key =
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEogIBAAKCAQEAllaf/na5h3yDr2zoYsYGGqt/d93/AAUTculGTXdGGbRwyHue\n"
"b0BaMeX+ht9siZ82iuaZ/5mJ/kq8WVwlrkegOAvU7SQDoALPM7VLMLSMbnn2Wqog\n"
"WE48TkWU0WddtTFHVDGLX8zMC1TQ1VKyVzp2QtCW9RPJNun9CVJSoZ34uM5hBL1f\n"
"7MY7t/QsDYi14UtULDsSnVz+tDLiPrBkZOPEVhopCH1gvljcDTcICfawyK5nlCKc\n"
"AnUWTHEUzf89WCJkPNk1W3LhscGKfx2bV8XVv+izg2zMLec5aYM/LrJg6HpJzgQJ\n"
"IKBt1tWQkxRvO7LO3znSp8A9DXotvr0MkIqcjQIDAQABAoIBAEMAaF3oW9deTvIn\n"
"/4nF54KLXEv3zGYd3QUhogt0VPGv0XQIZBwA+jGy5zUE7kKHiq9tBsU7kJycgkTx\n"
"JHn/whA4dbUaj+MIXYAWFGSoks3J3Vma6L9yXr4jlKefAcx3IesMCamwhF+odUod\n"
"iQ4HKB2vCRhAsTSgI/27isgst2TlJsGMf7ED2N1jae8ZyOITi2g0F1edRYBwgSHq\n"
"MZvccZh/IpuTOPEVxuITYyQT9WF0TCz7cK4wCP5dACQQB6Or8l2xiUf9dx3I7kwR\n"
"7wvivI+jAoxR/peOXx2o0bHPcqh41rbhbE00XOcIReGoyLsRDvicw3hgFe6UxcEm\n"
"PlpFzaECgYEAyBPpzK3x0iXj66iO6erXzciN5cXF8IZhC7xcCgGOpnjgrMV3FUNv\n"
"L0Qu8zUlTJHfWpITCZawPpbNMaNShykLU6NqxUPXGtaH/xVUZm9VbkRwBQoQKg+w\n"
"x2+hAWTGu4rWtSaWMHJuwI0SYyopvJtBgDO8PkmzDG24RQuRVBSE+ycCgYEAwFu6\n"
"QHVHvVm4ri1FCIK313uXTWoYhKDCm8ygDKT608bHzBoqOcXPT5mcr3IZmZitsg3Y\n"
"DyVvPGmmbLp8FmxXcz2c71e1Bupeq9V8HrMiSgMVPEIRuNKVC7WE/Ymuvpvfd+h/\n"
"RyDCu2wTI4GcJRhmAB+SpjPPOH0qaqV2eHZgSysCgYAO5eyy4QDwtQGTuqlpoaMQ\n"
"H67xPRjQIDF5vjzcQeFtY/LW6p1DaBIPYvRcB8kPOo13IQlp3V6iSnhdCdxLVDMT\n"
"t0dsCPErfm4CAISYXBHwdAgjV+x8NU7kittiTy69KEl0k7r7QIoerGKCH9GbybPG\n"
"6BNMUBCVDFZ8TbA0opKEYQKBgEl0/fxNjTbXA3qoWPt2B8SnMtFiWbiUN50NmHUb\n"
"r5meCIB94XAshQ2NyNMLDJGmR3Z+aOrnzcHRSresw2RAvWiJt9uCr+PTLpIKNZr3\n"
"p3mCEeLwDBp7eGV/TSkRIgUyOzVsOOatsQ+nputhPILB/XnAlN0ZXeHhkoglZcd8\n"
"1Sr/AoGAU7nlyAMQNd/tckwPTnM++0ewrFvwrfpS7f2dhcYbIhfqQ3I03Gwzjkkg\n"
"G85uzTg/8iO4oxPRjqPvc7JaoDDmGY/efQvjR+FdwDOuy+XZPImZIgGjl0yvAMFU\n"
"6azU+OxtwV+Yyfad4rGxaXZsqOIs18to94t2kjI0t8ur/4Q7C5w=\n"
"-----END RSA PRIVATE KEY-----\n"; // to verify the client
const char *test_client_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIDnjCCAoYCFBRQlTP3aMzr8YtFlYoaVtrPIN6xMA0GCSqGSIb3DQEBCwUAMIGH\n"
"MQswCQYDVQQGEwJWTjEQMA4GA1UECAwHdmlldG5hbTEQMA4GA1UEBwwHdmlldG5h\n"
"bTEOMAwGA1UECgwFcGVjb20xDTALBgNVBAsMBHRlc3QxDTALBgNVBAMMBG1xdHQx\n"
"JjAkBgkqhkiG9w0BCQEWF2NwdHByaWNlMTIzQG91dGxvb2suY29tMB4XDTIyMTEw\n"
"MzA4MTMzMVoXDTIzMDIxMTA4MTMzMVowgY4xCzAJBgNVBAYTAlZOMRAwDgYDVQQI\n"
"DAd2aWV0bmFtMRAwDgYDVQQHDAd2aWV0bmFtMQ4wDAYDVQQKDAVwZWNvbTENMAsG\n"
"A1UECwwEdGVzdDETMBEGA1UEAwwKbXF0dGNsaWVudDEnMCUGCSqGSIb3DQEJARYY\n"
"Y3B0cHJpY2VAMTIzQG91dGxvb2suY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n"
"MIIBCgKCAQEAllaf/na5h3yDr2zoYsYGGqt/d93/AAUTculGTXdGGbRwyHueb0Ba\n"
"MeX+ht9siZ82iuaZ/5mJ/kq8WVwlrkegOAvU7SQDoALPM7VLMLSMbnn2WqogWE48\n"
"TkWU0WddtTFHVDGLX8zMC1TQ1VKyVzp2QtCW9RPJNun9CVJSoZ34uM5hBL1f7MY7\n"
"t/QsDYi14UtULDsSnVz+tDLiPrBkZOPEVhopCH1gvljcDTcICfawyK5nlCKcAnUW\n"
"THEUzf89WCJkPNk1W3LhscGKfx2bV8XVv+izg2zMLec5aYM/LrJg6HpJzgQJIKBt\n"
"1tWQkxRvO7LO3znSp8A9DXotvr0MkIqcjQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\n"
"AQCF33dWLyL/QJKDBNtKc6WwmOn97u74jkIYdgRHgQwNvrmLHRgZPb6Bhzy5KAIY\n"
"qJcPA6Cn/m4utUWjAXRPj9zDT5xyeC843R22KQASjmPBnEyfDZuXmUPjjNJUSUx6\n"
"JGk/bwPQDLT2ID+vl3OInm4ypgwbGaqlhn41m0F2smanuZUFgEmN5+tJpkwK/tVP\n"
"IYHJ5HPnFqDFs84Fp12HU2QcqbOUEZ/d77Yw/dfb20cvgW2xkHKEAhz7d9EpD4ov\n"
"S5ZnelKxvqlVzI2v2I6MJkRdeP2IfYofNfRo2s7S5u+h/2SQu1MbbarS/jd32Ldz\n"
"14EVvDj+sCF2g7skdJ3kYCPI\n"
"-----END CERTIFICATE-----\n"; // to verify the client
Server config:
listen:0.0.0.0:4222
jetstream:{
max_memory_store: 1073741824
max_file_store: 1073741824
}
mqtt {
# Specify a host and port to listen for websocket connections
#
listen: "0.0.0.0:8883"
# It can also be configured with individual parameters,
# namely host and port.
#
# host: "hostname"
# port: 1883
# TLS configuration.
tls {
cert_file: /etc/tls/mqtt/broker/broker.crt
key_file: /etc/tls/mqtt/broker/broker.key
ca_file: /etc/tls/mqtt/ca/ca.crt
verify: true
timeout: 2.0
# verify_and_map: true
}
# no_auth_user: "my_username_for_apps_not_providing_credentials"
# authorization {
# # username: "my_user_name"
# # password: "my_password"
# # token: "my_token"
# # timeout: 2.0
# }
ack_wait: "1m"
max_ack_pending: 100
}
tls:{
cert_file: /etc/tls/natsio/server-cert.pem
key_file: /etc/tls/natsio/server-key.pem
ca_file: /etc/tls/natsio/ca-cert.pem
}
http_port: 8222
# system_account: AAOQAS43OSVDMF3ERYSNL3GMGZRD7GILDGDET6R52NFZKEWJOTTVNYZ4
# resolver: {
# type: full
# dir: './jwt'
# allow_delete: false
# interval: "2m"
# limit: 1000
# }
Logs from NATS server:
test-nats-dev-1 | [1] 2022/11/03 10:29:32.794114 [ERR] 192.168.1.14:57479 - mid:699 - TLS handshake error: remote error: tls: bad certificate
test-nats-dev-1 | [1] 2022/11/03 10:29:37.989099 [ERR] 192.168.1.14:57480 - mid:700 - TLS handshake error: remote error: tls: bad certificate
ESP32 logs:
Attempting MQTT connection...[2959556][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():276]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[2959559][E][WiFiClientSecure.cpp:135] connect(): start_ssl_client: -9984
failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...[2964762][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():276]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[2964765][E][WiFiClientSecure.cpp:135] connect(): start_ssl_client: -9984
failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...[2976298][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():276]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[2976301][E][WiFiClientSecure.cpp:135] connect(): start_ssl_client: -9984
failed, rc=-2 try again in 5 seconds
I found the problem is my cert is using domain for certification and I using IP for connection. That is make it not working.
After change to using domain in connection it works normally.
Domain TLS: https://docs.cpanel.net/knowledge-base/general-systems-administration/what-is-domain-tls/
IP TLS: Is it possible to have SSL certificate for IP address, not domain name?
I'm running a java app in JBoss 6.4.0 in an Amazon Web Services red hat 8 EC2 instance.
When my app tries to send an email via javax.mail I'm getting an error "Could not convert socket to TLS".
I then coded up the AmazonSESSample.java sample program and tried it. I ran it in my EC2 instance outside JBoss and it ran successfully. (The AmazonSESSample program can be found here: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/examples-send-using-smtp.html)
Then I commented out the email code in my java app, and replaced it with the code in AmazonSESSample.java. When I run my java app with the AmazonSESSample code in JBoss I get the same error: "Could not convert socket to TLS". So the AmazonSESSample works fine outside JBoss, and gives an error when running inside JBoss.
Here is the AmazonSESSample code in my app. Can somebody help me fix the "Could not convert socket to TLS" error?:
public class AmazonSESSample {
private static final Logger logger = LogManager.getFormatterLogger("AmazonSESSample");
// Replace sender#example.com with your "From" address.
// This address must be verified.
static final String FROM = "email1#gmail.com";
static final String FROMNAME = "Steve";
// Replace recipient#example.com with a "To" address. If your account
// is still in the sandbox, this address must be verified.
static final String TO = "email2#gmail.com";
// Replace smtp_username with your Amazon SES SMTP user name.
static final String SMTP_USERNAME = "thisIsNotActualghijikl";
// Replace smtp_password with your Amazon SES SMTP password.
static final String SMTP_PASSWORD = "abcdefThisIsNotActual";
// Amazon SES SMTP host name. This example uses the US West (Oregon) region.
// See https://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html#region-endpoints
// for more information.
static final String HOST = "email-smtp.us-east-2.amazonaws.com";
// The port you will connect to on the Amazon SES SMTP endpoint.
static final int PORT = 587;
static final String SUBJECT = "Amazon SES test (SMTP interface accessed using Java)";
static final String BODY = String.join(
System.getProperty("line.separator"),
"<h1>Amazon SES SMTP Email Test</h1>",
"<p>This email was sent with Amazon SES using the ",
"<a href='https://github.com/javaee/javamail'>Javamail Package</a>",
" for <a href='https://www.java.com'>Java</a>."
);
public int sendEmail(DisplayEmailMessage emailMessage) throws UnsupportedEncodingException, MessagingException {
// Create a Properties object to contain connection configuration information.
Properties props = System.getProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.port", PORT);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
// Create a Session object to represent a mail session with the specified properties.
Session session = Session.getDefaultInstance(props);
// Create a message with the specified information.
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(FROM, FROMNAME));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(TO));
msg.setSubject(SUBJECT);
msg.setContent(BODY, "text/html");
// Create a transport.
Transport transport = session.getTransport();
// Send the message.
try {
System.out.println("Sending...");
// Connect to Amazon SES using the SMTP username and password you specified above.
transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD);
// Send the email.
transport.sendMessage(msg, msg.getAllRecipients());
System.out.println("Email sent!");
}
catch (Exception ex) {
System.out.println("The email was not sent.");
System.out.println("Error message: " + ex.getMessage());
}
finally {
// Close and terminate the connection.
transport.close();
}
return 0;
}
}
Here is the javamail debug output:
DEBUG: setDebug: JavaMail version 1.4.5.redhat-2
Sending email to 123#gmail.com
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
Starting to connect at Sun Dec 26 13:14:23 UTC 2021 to email 123#gmail.com
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.dreamhost.com", port 587, isSSL false
220 pdx1-sub0-mail-a290.dreamhost.com ESMTP
DEBUG SMTP: connected to host "smtp.dreamhost.com", port: 587
EHLO ip-172-31-29-30.us-east-2.compute.internal
250-pdx1-sub0-mail-a290.dreamhost.com
250-PIPELINING
250-SIZE 40960000
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 CHUNKING
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "SIZE", arg "40960000"
DEBUG SMTP: Found extension "ETRN", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "AUTH=PLAIN", arg "LOGIN"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
STARTTLS
220 2.0.0 Ready to start TLS
MessagingException
javax.mail.MessagingException: Could not convert socket to TLS
I fixed this by upgrading my JBoss to 7.4.0.
Since all the certs from websites are signed by Root CA's and such, and I am writing a client, not a server, how would I create an SSLEngine that can connect to them all? or do I have to download certs and such to connect? (I am hoping that jdk has all the same info as the browsers regarding certs and such so doing this should be easy although I am having trouble with my google skills in finding it since most links are servers).
EDIT: For more clarity, I have client code like so that works with a self-signed cert. Currently, I downloaded the cert from the website I wanted through chrome clicking on the lock. I then imported that into my keystore but it's still not working...
private SSLEngine createEngine() {
try {
InputStream in = this.getClass().getResourceAsStream("/prodKeyStore.jks");
//char[] passphrase = password.toCharArray();
// First initialize the key and trust material.
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, "lP9Ow1uYXZr9zgt6".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
//****************Client side specific*********************
// TrustManager's decide whether to allow connections.
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
sslContext.init(null, tmf.getTrustManagers(), null);
//****************Client side specific*********************
SSLEngine engine = sslContext.createSSLEngine();
engine.setUseClientMode(true);
return engine;
} catch(Exception e) {
throw new RuntimeException("Could not create SSLEngine", e);
}
}
Next, I am going to try to figure out how to turn debug on for ssl exchange and see if that helps any. Currently, I am at a loss as to why this is not working.
OUCH, debug logs point to this
javax.net.ssl|DEBUG|21|httpclient2|2020-02-18 08:13:05.095 MST|CertificateMessage.java:358|Consuming server Certificate handshake message (
"Certificates": [
"certificate" : {
"version" : "v3",
"serial number" : "00 90 76 89 18 E9 33 93 A0",
"signature algorithm": "SHA256withRSA",
"issuer" : "CN=invalid2.invalid, OU="No SNI provided; please fix your client."",
"not before" : "2014-12-31 17:00:00.000 MST",
"not after" : "2029-12-31 17:00:00.000 MST",
"subject" : "CN=invalid2.invalid, OU="No SNI provided; please fix your client."",
"subject public key" : "RSA",
"extensions" : [
so something is screwing things up bigtime but not sure what yet. This is jdk8. Not sure how to fix this yet.
thanks,
Dean
It turned out there is one line wrong and it has to be this
SSLEngine engine = sslContext.createSSLEngine(host, port);
and then it all works!
I am trying to connect to S3 from EC2 instance using AmazonS3Client, to get the list of objects present in S3 bucket. While I can connect to S3 when running this code from my local machine, I am having a hard time running the same code on EC2.
Am I missing any setting or configuration on EC2 instance?
Code
AWSCredentials credentials = new BasicAWSCredentials("XXXX", "YYYY");
AmazonS3Client conn = new AmazonS3Client(credentials);
String bucketName = "s3-xyz";
String prefix = "123";
ObjectListing objects = conn.listObjects(bucketName, prefix);
List<S3ObjectSummary> objectSummary = objects.getObjectSummaries();
for(S3ObjectSummary os : objectSummary)
{
System.out.println(os.getKey());
}
Errors
ERROR com.amazonaws.http.AmazonHttpClient - Unable to execute HTTP request: Connect to s3-xyz.amazonaws.com:443 timed out
org.apache.http.conn.ConnectTimeoutException: Connect to s3-xyz.s3.amazonaws.com:443 timed out
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:551)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:318)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:202)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3037)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3008)
at com.amazonaws.services.s3.AmazonS3Client.listObjects(AmazonS3Client.java:531)
at com.amazonaws.services.s3.AmazonS3Client.listObjects(AmazonS3Client.java:515)
ClientConfiguration cc = new ClientConfiguration();
cc.setProxyHost("10.66.80.122");
cc.setProxyPort(8080);
propertiesCredentials = new BasicAWSCredentials(aws_access_key_id, aws_secret_access_key);
s3 = new AmazonS3Client(propertiesCredentials,cc);
To find proxy_host & port go to LAN settings.