Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generate web certificate self signed by CA #46

Merged
merged 8 commits into from
Dec 10, 2020

Conversation

macintoshplus
Copy link
Contributor

@macintoshplus macintoshplus commented Dec 2, 2020

This PR allow generate SSL certificate for CA and Web Certificate for localhost, 127.0.0.1 and ::1.

Fix partially #45

Result on Firefox:

image

Chromium:

image

ToDo:

  • generate CA
  • generate Web Certificate
  • Sign Web Certificate with CA
  • Install the CA Certificate into Operating System

@macintoshplus
Copy link
Contributor Author

The server:ca:install command is added with process for Linux Ubuntu (test in progress), macOs and Windows.

The file .rymfony/tls_cert.pem containt the web certificate and the CA Root certifcate. Now the server provide to browser all certificat chain.

After install Certificat Authority on system, curl work fine (without -k option):

 curl -v https://127.0.0.1:8000
*   Trying 127.0.0.1:8000...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=FR; O=Orbitale.io cert (dev); OU=Orbitale localhost (dev)
*  start date: Dec  3 22:01:43 2020 GMT
*  expire date: Dec  3 22:01:43 2021 GMT
*  subjectAltName: host "127.0.0.1" matched cert's IP address!
*  issuer: C=FR; O=Orbitale.io; OU=Orbitale.io localhost; CN=Orbitale CA (dev)
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x559835e15db0)
> GET / HTTP/2
> Host: 127.0.0.1:8000
> user-agent: curl/7.68.0
> accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
< HTTP/2 200 
< content-length: 976
< x-some-random-header: some-random-value
< content-type: text/plain;charset=UTF-8
< date: Thu, 03 Dec 2020 22:11:16 GMT
< 
Hey! It works!
{
    "Date": "2020-12-03 23:11:16",
    "Server parameters": {
        "CONTENT_LENGTH": "",
        "CONTENT_TYPE": "",
        "DOCUMENT_ROOT": "/home/xxxx/Dev/Rymfony",
        "DOCUMENT_URI": "/",
        "GATEWAY_INTERFACE": "FastCGI/1.0",
        "HTTPS": "On",
        "ORIG_PATH_INFO": "__",
        "PATH_INFO": "",
        "QUERY_STRING": "",
        "REMOTE_ADDR": "127.0.0.1",
        "REMOTE_HOST": "__",
        "REMOTE_PORT": "60000",
        "REQUEST_METHOD": "GET",
        "REQUEST_URI": "/",
        "SCRIPT_FILENAME": "/home/xxxx/Dev/Rymfony/index.php",
        "SCRIPT_NAME": "/index.php",
        "SERVER_ADDR": "__",
        "SERVER_ADMIN": "__",
        "SERVER_NAME": "127.0.0.1",
        "SERVER_PORT": "8000",
        "SERVER_PROTOCOL": "HTTP/1.1",
        "SERVER_SOFTWARE": "Rymfony v0.1.0"
    },
    "Request headers": {
        "HTTP_ACCEPT": "*/*",
        "HTTP_USER_AGENT": "curl/7.68.0"
    },
    "Request body": ""
* Connection #0 to host 127.0.0.1 left intact
}

Unfortunately no browser accept the CA Root.

Copy link
Member

@Pierstoval Pierstoval left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some suggestions and added some questions regarding this enchanting PR 👍

  • Informational messages should add value to the end user, and you display the exit status for runa commands, which doesn't realy add value IMO. I think that maybe you could keep them using trace!() instead of info!(), and perhaps use info!() to display only some "success" message that tell the user what the process is doing :)
  • We need to make sure the CA directory is the same for all distros, I'd like some research or feedback before we push it, or at least we should add more verbose warnings to users (like telling them that "the CA dir wasn't found in {checked_location}" for instance)
  • I'd even suggest a way to customize it with an env var, something like RYMFONY_CA_DIR, so people doing weird stuff, or unknown distros, can still have a workaround.

I'm so glad you worked on this! This was on the top of the roadmap, so thanks a lot 👍

src/commands/ca_install.rs Outdated Show resolved Hide resolved
src/commands/ca_install.rs Outdated Show resolved Hide resolved
if cfg!(target_os = "windows") {
window_ca_install(&certificate_path);
} else if cfg!(target_os = "linux") {
ubuntu_ca_install(&certificate_path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ubuntu_ca_install(&certificate_path);
linux_ca_install(&certificate_path);

// writeln!("End Of Work");
}

fn ubuntu_ca_install(certificate_path: &PathBuf) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn ubuntu_ca_install(certificate_path: &PathBuf) {
fn linux_ca_install(certificate_path: &PathBuf) {

}

fn ubuntu_ca_install(certificate_path: &PathBuf) {
let ubuntu_cert_path = PathBuf::from("/usr/local/share/ca-certificates/");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make sure this is the same path for other distros than Ubuntu. Did you check for Alpine, Arch, RedHat or others?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This process is good for all Debian based distros.

I don't know for other distros. I need search how to it.

src/commands/ca_install.rs Outdated Show resolved Hide resolved
src/commands/ca_install.rs Outdated Show resolved Hide resolved
src/config/certificates.rs Outdated Show resolved Hide resolved
Comment on lines +197 to +201
let subject_alt_name = SubjectAlternativeName::new()
.dns("localhost")
.ip("127.0.0.1")
.ip("::1")
.build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curiosity here: Do you think we could somehow "externalize" this part in order to allow users to create CA/certs for custom local domains in the future? Symfony CLI is doing it but only with the .wip domain, I'd personally like users to be able to add any domain (some people use .docker or .local for instance).

At some point, it could even use runa to open /etc/hosts / c:\Windows\system32\drivers\etc\hosts in order to add the domain and make it point to 127.0.0.1 without the user having to do it themselves (which would be kind of a revolution, since no dnsmasq config or anything, means a lot!)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have same idea. Add command to add domain into certificate.
The list of domain can be stored into .rymfony directory and used to update the hosts file (with specific command).

But :

  • If a domain is already in hosts file, do not add.
  • add comment into hosts file to prevent change this section? Like Flex add in .env file on install.

Preview:

### Rymfony Domain
127.0.0.1 my-domain.local
::1 my-domain.local
127.0.0.1 admin.my-domain.local
::1 admin.my-domain.local
### END Rymfony Domain

Add this feature is for an new PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a domain is already in hosts file, do not add.

Seems obvious to me to avoid duplications 👍

add comment into hosts file to prevent change this section? Like Flex add in .env file on install.

I like the idea, Docker Desktop does it too, but I think it might over-complexify the process. If you already know how to do that with good performances, that may be good, but I think it might introduce a bit of overhead. Also, it is error-prone if anyone modifies the comment section (that's also one problem with Flex, by the way).

I think one line-comment could be good, like this:

127.0.0.1 my-domain.local # Added by Rymfony
::1 my-domain.local # Added by Rymfony

And for the "where do we put this", this could be on top of the file.
We could put it after all the comments lines that serve as disclaimer on Windows for example. It's easy to check (open the file, check the first characters of the line, and if it's # or a non-empty trimmed line, move to next line).

I'm also okay for a second PR :)

src/commands/ca_install.rs Show resolved Hide resolved
@macintoshplus
Copy link
Contributor Author

  • We need to make sure the CA directory is the same for all distros, I'd like some research or feedback before we push it, or at least we should add more verbose warnings to users (like telling them that "the CA dir wasn't found in {checked_location}" for instance)

The folder and the process can be changed between Linux distribution. That's why I put the name of the function with ubuntu

One of source used to know how to add CA Root on systems: https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html

If no folder is found, I suggest to inform the user of the location of the CA Root to add itself into their system.

  • I'd even suggest a way to customize it with an env var, something like RYMFONY_CA_DIR, so people doing weird stuff, or unknown distros, can still have a workaround.

As the process to add a CA Root into *nix system is not same, this env var cannot be used.

I'm so glad you worked on this! This was on the top of the roadmap, so thanks a lot

I'm glad you enjoyed my work. I've wanted to use Rust for a long time. But I never had a really serious project. Your live on Rust development for PHP developers introduced me to your project. 😃

@macintoshplus macintoshplus changed the title generate web certificate self signed by CA WIP: generate web certificate self signed by CA Dec 4, 2020
@Pierstoval
Copy link
Member

Thanks for the clarification about CA root on *nix systems 👍

We'll keep the code as-is with your PR, and if anyone has issue, we'll change it then 😉

@Pierstoval
Copy link
Member

Pierstoval commented Dec 5, 2020

I just tested this branch locally, removed existing certificates in ~/.rymfony/, used server:ca:install and when I curl the server on Windows, I have to use --insecure or --ssl-no-revoke to make it work.

Here's what I got:

$ curl -i https://127.0.0.1:8000/
curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - La fonction de révocation n’a pas pu vérifier la révocation du certificat.

No idea on what's going on though, nor whether it is a bug 🤣

@macintoshplus
Copy link
Contributor Author

I have tested only on Linux Mint this feature.

You have run rymfony on WSDL ? What is your configuration ?

@Pierstoval
Copy link
Member

I'm running it with Powershell on a native Windows 10 Pro machine.

I have tested with WSL and it works normally :)

@macintoshplus
Copy link
Contributor Author

Curl on windows don't use the system certificate manager. You need add the Rymfony CA Root into the CA bundle curl-ca-bundle.crt located in same directory of curl.exe

@macintoshplus macintoshplus changed the title WIP: generate web certificate self signed by CA generate web certificate self signed by CA Dec 5, 2020
@Pierstoval
Copy link
Member

Ok, I'm using the curl.exe executable that's built-in Windows 10. I will try to find a way to use the latest version of Curl and retry :)

@macintoshplus macintoshplus mentioned this pull request Dec 5, 2020
@Pierstoval
Copy link
Member

Now I have an other error:

$ curl -i https://127.0.0.1:8000/
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Removing certs in ~/.rymfony/ and using server:ca:uninstall + server:ca:install doesn't fix the issue.

Note:

$ curl --version
curl 7.73.0 (x86_64-pc-win32) libcurl/7.73.0 OpenSSL/1.1.1h (Schannel) zlib/1.2.11 brotli/1.0.9 zstd/1.4.5 WinIDN libssh2/1.9.0 nghttp2/1.42.0
Release-Date: 2020-10-14
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile MultiSSL NTLM SPNEGO SSL SSPI TLS-SRP Unicode UnixSockets brotli libz zstd

@macintoshplus
Copy link
Contributor Author

The command server:ca:uninstall cannot remove certificate on Windows if the CA Root is not found on .rymfony directory.

Have you add the Rymfony CA root into the cURL ca bundle ?

@Pierstoval
Copy link
Member

Well, I couldn't successfully add it to Windows, but when using Curl's --cacert option, it works 👍

@macintoshplus
Copy link
Contributor Author

Firefox, Chromium and Edge works too?

@Pierstoval
Copy link
Member

Could test Firefox, Brave, IE and Edge, and it works 👍

I think we can merge it, don't you think?

@macintoshplus
Copy link
Contributor Author

Yes you can merge.

@Pierstoval Pierstoval merged commit 9e01ca3 into Orbitale:main Dec 10, 2020
@Pierstoval
Copy link
Member

Thank you @macintoshplus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants