Generate SSL certificates for multiple domains in SubjectAltName with Greenlock - node.js

I'm using greenlock to generate certificates, I pass it three domains, and only get 2 in my altnames:
const greenlock = Greenlock.create({
agreeTos: true,
email: myemail,
communityMember: false,
version: 'draft-12',
server: 'https://acme-v02.api.letsencrypt.org/directory',
configDir: '/etc/letsencrypt',
debug: true,
log: (debug) => { console.log(debug) },
})
console.log({ domains })
return greenlock.register({
domains,
email: myemail,
challengeType: 'dns-01',
})
.then((result) => {
console.log(result)
})
here are my logs:
{ domains:
[ 'domain1',
'domain3',
'domain2' ] }
true
true
true
{ result:
{
privkey: '-----BEGIN PRIVATE KEY-----\n\n-----END CERTIFICATE-----\n',
chain: '-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n',
subject: 'domain2',
altnames: [ 'domain1', 'domain2' ],
_issuedAt: 2018-09-19T14:43:31.000Z,
_expiresAt: 2018-12-18T14:43:31.000Z,
issuedAt: 1537368211000,
expiresAt: 1545144211000 } }
As you can see it's not even my first two domains that end up in my altnames but rather those that where already in the old certificate (not sure this is why tho).
I'm not married to greenlock, if someone as a better alternative I'm listening as well.
I tried passing approveDomains to my greenlock constructor and it doesn't seem to change much.
I still don't have my new domain (domain2) listed in my certificate :
openssl x509 -text < /etc/letsencrypt/live/domain1/fullchain.pem | grep 'DNS:' | sed 's/\s*DNS:\([a-z0-9.\-]*\)[,\s]\?/\1 /g'
domain1 domain3

Use Greenlock v2.7+
All of the code related to certificate generation and domain name and altname association has been updated.
Now when you change the domains array to include more domains it handles them individually rather than as a group.
Also, the information about the certificate is read directly from the certificate, so there can't be a mismatch between the "cache" and "the truth".
If you encounter further issues, please let us know directly:
https://git.rootprojects.org/root/greenlock.js/issues

Related

Failed to connect to all addresses - gRPC with Go and NodeJS

"Failed to connect to all addresses" occurs while adding TLS certs to envoy.yaml, full error:
code: 14,
metadata: Metadata { _internal_repr: {}, flags: 0 },
details: 'failed to connect to all addresses'
Envoy config (Envoy is running on port 50000, and itemService on 50052):
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"#type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain:
filename: server.cert
private_key:
filename: server.key
Client code Nodejs - (NextJS on server side - getServerSideProps)
options = {
key: readFileSync("certs/client.key"),
cert: readFileSync("certs/ca.crt"),
csr: readFileSync("certs/client.crt"),
};
const creds = credentials.createSsl(
options.cert,
options.key,
options.csr
);
grpcServer.servicesList.itemsService = new ItemsServiceClient(
"localhost:50000",
creds,
{
"grpc.ssl_target_name_override": "localhost",
"grpc.default_authority": "localhost",
}
);
Request works normally when removing TLS certs from envoy.yaml.
Error I get from grpcurl tool: Failed to dial target host "localhost:50000" x509: certificate relies on legacy Common Name field, use SANs instead.
When I set GODEBUG=x509ignoreCN=0, seems like error stays same.

MySQL xdevapi Node Error: SELF_SIGNED_CERT_IN_CHAIN

Windows 10 Pro
MySQL8.0
node.js v14.15.5
openssl 1.1.1c
I'm trying to connect to a MySQL database using node, I'm able to connect without TLS just fine. I used openssl to create a private key and self signed certificate. When I try to use TLS in my node app, I keep getting the following error:
$ NODE_TLS_REJECT_UNAUTHORIZED=0 node index.js
(node:15480) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
Error: self signed certificate in certificate chain
at TLSSocket.onConnectSecure (_tls_wrap.js:1497:34)
at TLSSocket.emit (events.js:315:20)
at TLSSocket._finishInit (_tls_wrap.js:932:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:706:12) {
code: 'SELF_SIGNED_CERT_IN_CHAIN'
}
TypeError: Cannot read property 'sql' of undefined
at C:\Users\gregb\Desktop\PROGRAMMING\VS Code Workspace\xdevapi2\index.js:40:32
at processTicksAndRejections (internal/process/task_queues.js:93:5)
[]
[]
Index.js
let mysqlx = require('#mysql/xdevapi');
let fs = require('fs');
require('dotenv').config();
let rows = [];
let columns = [];
// Works without TLS
// let config = {
// host: 'localhost',
// port: 33060,
// user: 'root',
// database: 'user',
// password: process.env.password
// };
const config = {
host: 'localhost',
port: 33060,
user: 'root',
database: 'user',
password: process.env.password,
ssl: true,
tls: {
rejectUnauthorized: false,
key: fs.readFileSync('./privatekey2.pem'),
cert: fs.readFileSync('./example.crt'),
ca: './cacert.pem'
}
};
(async function () {
let session;
try {
session = await mysqlx.getSession(config);
} catch(err) {
console.log(err);
}
try {
let result = await session.sql('SELECT "firstName" AS c1, "lastName" AS c2')
.execute(row => rows.push(row), column => columns = columns.concat(column));
session.close();
} catch(err) {
console.log(err);
}
console.log(rows); // [['foo', 'bar']]
console.log(columns.map(column => column.getColumnLabel())); // ['c1', 'c2']
})();
I also tried:
NODE_TLS_REJECT_UNAUTHORIZED='0' node index.js
How I used openssl:
Create a public/private key file pair:
openssl genrsa -out privkey2.pem 4096
Split into public/private:
openssl ssh-keygen -t rsa -b 4096 -f privatekey2.pem
Create a cert
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout privatekey2.pem -out example.crt
The problem does not seem to be related to the certificate you are using. It should be related to the fact that you provide a path for the certificate authority file (ca). You do this when you want the client to verify that the server certificate was signed using a certificate in the CA chain, which only works if rejectUnauthorized is true, which is automatically set once you provide that valid CA file path, thus, your custom rejectUnauthorized: false is ignored.
Which begs the question, Is the server certificate signed by the CA you are providing? I suspect it is not, in which case, the error is legitimate.
If so, then it is a bug, and you should report it using the public MySQL issue tracker. However, I ran a few tests and I'm convinced there is no issue, but if you are able to produce a server certificate that was, indeed, signed by that particular CA, which allows to reproduce the same exact scenario, maybe we can dig some dirt.
Disclaimer: I'm the lead developer of MySQL X DevAPI Connector for Node.js

Getting MongooseServerSelectionError: Hostname/IP does not match certificate's altnames: IP: xxx.xx.xx.xx is not in the cert's list:

I have created self signed certificate in my linux machine where i have given certificate CN same as IP of that linux
I have added them in mongodb.conf and restarted the server
i am able to connecte via command
mongo --ssl --sslPEMKeyFile /etc/ssl/mongodbcerts/mongodb.pem --sslCAFile /etc/ssl/mongodbcerts/ca.pem
But when i am trying to connect from nodeJS mongoose i am getting error like
MongooseServerSelectionError: Hostname/IP does not match certificate's altnames: IP: XXX.xx.x.xx is not in the cert's list:
My nodejs code for connecting mongodb as follows
const connectionOptions = { useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false ,
server:{
ssl: true,
sslValidate:true,
sslCA: require('fs').readFileSync("/etc/ssl/mongodbcerts/ca.pem"),
sslKey:require('fs').readFileSync("/etc/ssl/mongodbcerts/mongodb.key"),
sslCert:require('fs').readFileSync("/etc/ssl/mongodbcerts/mongodb.crt")
}
};
let mongo_url="mongodb://username:password#IPaddress/DB"
console.log(mongo_url)
mongoose.connect(mongo_url,connectionOptions).then(() => console.log( 'Database Connected' ))
.catch(err => console.log( err ));;
Please let me know the error
I faced this issue recently. Starting in MongoDB 4.2, when performing comparison of SAN, MongoDB supports comparison of IP addresses as well. You can use IP address in the CN field but make sure your openssl configuration file contains your servers IP address in the alt_names section.
Here's a sample cnf file provided in the official MongoDB docs -
# NOT FOR PRODUCTION USE. OpenSSL configuration file for testing.
[ req ]
default_bits = 4096
default_keyfile = myTestServerCertificateKey.pem ## The default private key file name.
default_md = sha256
distinguished_name = req_dn
req_extensions = v3_req
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
nsComment = "OpenSSL Generated Certificate for TESTING only. NOT FOR PRODUCTION USE."
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = ##TODO: Enter the DNS names if using hostname, otherwise remove this line
IP.1 = ##TODO: Enter the IP address if using IP address
[ req_dn ]
countryName = Country Name (2 letter code)
countryName_default = TestServerCertificateCountry
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = TestServerCertificateState
stateOrProvinceName_max = 64
localityName = Locality Name (eg, city)
localityName_default = TestServerCertificateLocality
localityName_max = 64
organizationName = Organization Name (eg, company)
organizationName_default = TestServerCertificateOrg
organizationName_max = 64
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = TestServerCertificateOrgUnit
organizationalUnitName_max = 64
commonName = Common Name (eg, YOUR name)
commonName_max = 64
Mistake i did was I have created self signed certificate with Common Name(CN) as IP address (XXX.xx.x.xx) but we need to create the self signed certificates with CN as hostname.
To get the hostname open mongo shell and execute below command:
>getHostName()
You will hostname of that VM and create self signed certificates with same host name and try connect with mongoose nodejs. It will work.
Support Doc: https://mongoosejs.com/docs/tutorials/ssl.html

How to create a Certificate Authority 'CA' using pem lib NodeJs?

Creating a CA using node
This is how to create a certificate using OpenSSL
OpenSSL Certificate Authority
I tried with pem
This is my closed Issue can't create CSR from private key #244 GitHub
When I trying to generate a CSR
var csrOptions = {
clientKey: '/root/ca/intermediate/private/client.key.pem',
clientKeyPassword: '123456',
hash: 'sha256',
country: 'US',
state: 'California',
locality: 'Mountain View',
organization: 'Alice Ltd',
organizationUnit: 'Alice Ltd Web Services',
commonName: 'pass:client',
}
pem.createCSR( csrOptions , function(err, csr) {
if (err) {
throw err
} else {
console.log(csr.clientKey)
console.log(csr.csr)
}
});
I get this error
/root/sslnode/index2.js:37
throw err
^
% openssl req -new -sha256 -config /root/ca/intermediate/openssl.cnf -key /tmp/54f976cb9cbd0e2dd53b755badb6e6e3fe2256ad -passin file:/tmp/3f4640f1d95ca955f1c44c7f2c4b729347813a5f
unable to load Private Key
140563986715072:error:0906D06C:PEM routines:PEM_read_bio:no start >line:../crypto/pem/pem_lib.c:691:Expecting: ANY PRIVATE KEY
After searching I get the error, clientKey took a key as a string, not a path
clientKey: '/root/ca/intermediate/private/client.key.pem',
clientKey: fs.readFileSync('/root/ca/intermediate/private/client.key.pem'),

How to add pem files to target in flightplan automated deployment script for nodejs applications

I am new to node applications deployment, I am using flightplan.js for automated deployments, however in most of the documents I have seen it is only about password less deployments where a user's key is added to server, I want to set up the target where I can specify the location of pem file in order to login to the server, is there a way to do that? right now the target looks like this
plan.target('staging', [
{
host: 'xxx.xxx.xxx',
username: username,
agent: process.env.SSH_AUTH_SOCK
}
]);
I would like to have something where I can pass the pem file path as well, something like this
plan.target('staging', [
{
host: 'xxx.xxx.xxx',
username: username,
key: PATH_TO_KEY
agent: process.env.SSH_AUTH_SOCK
}
]);
You can add your pem files like this,
plan.target('staging', [
{
host: 'xxx.xxx.xxx',
username: username,
privateKey: 'path/to/file/key.pem',
agent: process.env.SSH_AUTH_SOCK
}
]);

Resources