github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/design/https-acme/README.md (about) 1 ### Story 2 As a Heeus user I want my application to be requested using HTTPS 3 4 ### Terms 5 - HTTPS hypertext protocol which uses TLS encryption protocol to encypt communications 6 - TLS - Transport Level Security 7 - SSL - Secure Sockets Layer. TLS was known as SSL a time ago. Currently `SSL` term is used instead of `TLS` 8 9 ### Solution principles 10 - Request is always sent to a certain cluster (e.g. Main Cluster) 11 - Each cluster has its own domain 12 - We do NOT use Federation Domain/GEO-DNS 13 - ACME provider ([Let's Encrypt](https://letsencrypt.org/)) is used to get HTTPS certificates 14 - Let's Encrypt currently does not support wildcard certficates (DNS records SOA) 15 - one certificate covers all sites (DNS records A and CNAME) of the domain 16 - certificate for `localhost` can not be issued 17 - ACME v2 protocol version is used 18 - Certificate is obtained for each domain name. No wildcard certificates. 19 20 ### Concepts 21 - Register a domain name for each cluster 22 - Open ports 443 and 80 23 - Launch `ce server --ihttp.Port=443 --ihttp.ACME=true --ihttp.ClusterDomainBase="<cluster domain name base>"`, e.g. `example.com` 24 - `--ihttp.ClusterDomainBase` should contain the minimum accepted cluster domain name part. e.g. `example.com` specified -> `example.com`, `www.example.com`, `cluster1.example.com` etc are accepted 25 - `--ihttp.ClusterDomainBase` is needed to Let's Encrypt's HTTP01 challenge only 26 - `--ihttp.ACME=true` -> Let's Encrypt provider will be used. `--ihttp.Port` is 443 by default 27 - `--ihttp.ACME=true` -> `--ihttp.Port` must not be 80 (since it will be used to handle ACME protocol) 28 - `--ihttp.ACME` is not specified or `false` -> HTTP will be used instead of HTTPS, `--ihttp.Port` could be any: 80, 443 etc 29 30 ### Subdomains vs subdirectories 31 - Google idexing algorhithms treats subdomains as standalone sites. Content of a subdomains is not taken is account when ranking the root domain. 32 - practical impact on the SEO should be checked to choose between subdomains and subfolders 33 - want web search over entites of your business be more relevant -> use subfolders 34 - have completely different parts of a business not related to each other (e.g. 2 enterprises in one main domain) -> use subdomains 35 - want technically spread features of the site over different machines -> use subdomains, each feature in own subdomain, e.g. blog.example.com, shop.example.com 36 - there are no technical restrictions, legal restrictions in different countries, etc. -> use subfolders 37 38 ### Components 39 ```mermaid 40 erDiagram 41 IHTTPProcessor ||..|| httpProcessor : "implemented by" 42 ihttpimpl_New ||..|| httpProcessor : "creates and returns" 43 ihttpimpl_New ||..|| certManager : "creates *autocert.Manager{}" 44 ihttpimpl_New ||..|| clusterName : "accepts string" 45 httpProcessor ||..|| server : "has *http.Server{}" 46 httpProcessor ||..|| serverACME : "has *http.Server{}" 47 certStorage ||..|| routerAppStorage : "Get()/Put()" 48 routerAppStorage ||..|| istorage_IAppStorage : is 49 ihttpimpl_New ||..|| certStorage : "accepts *autocert.Cache interface" 50 serverACME ||..|| HTTPHandler : "uses" 51 TLSConfig ||..|| GetCertificate : "uses" 52 server ||..|| TLSConfig : "has *crypto/tls.Config{}" 53 certManager ||..|| HTTPHandler : "has method" 54 certManager ||..|| GetCertificate : "has method" 55 certManager ||..|| Cache : "has *autocert.Cache field" 56 certManager ||..|| HostPolicy :"has func field" 57 Cache ||..|| certStorage : "implemented by" 58 GetCertificate ||..|| Cache : "writes ACME token" 59 HostPolicy ||..|| HostWhiteList: "implemented by autocert.HostWhiteList" 60 HostWhiteList ||..|| clusterName : "uses" 61 HTTPHandler ||..|| Cache : "reads ACME token" 62 ``` 63 64 ### Establishing the HTTPS communication 65 - A user opens a web page using https:// scheme 66 - Request is got by one of Heeus CE instances by its http server on a port number 443 67 - HTTP server obtains a certificate to encrypt the communication 68 - Already has a certificate in the storage - use it 69 - Missing\expired\broken etc certificate -> obtain a new certificate from Let's Encrypt 70 - `autocert` library sends a request to Let's Encrypt server to issue a new certificate 71 - Let's Encrypt sends request to the Cluster Domain on port 80 (handled by `autocert` library) to check if the server actually controls the domain 72 - Reply from `autocert` is matched the initial request -> Let's Encrypt issues and returns a new certificate 73 - Cetificate is written to the storage 74 - Further communication between client and Heeus CE is encrypted using the certificate 75 ```mermaid 76 sequenceDiagram 77 participant b as browser 78 participant s as server(Heeus) 79 participant m as certManager(autocert) 80 participant c as certStorage(Heeus) 81 participant h as HTTPHandler(autocert) 82 participant sACME as serverACME(Heeus) 83 participant l as Let's Encrypt server 84 Note over s,sACME: httpProcessor 85 b->>s: https://example.com 86 activate s 87 s->>m: http.Server.TLSConfig.GetCertificate() 88 activate m 89 m->>c: Get() 90 activate c 91 c->>m: certificate or nil 92 deactivate c 93 opt certificate is nil 94 m->>c: Put(ACME token) 95 m->>l: send ACME token + request a new certificate for domain example.com 96 activate l 97 l->>sACME: if the request chained to you? 98 activate sACME 99 Note over l,sACME: http://example.com 100 sACME->>h: calls HTTPHandler() 101 activate h 102 h->>c: Get() 103 activate c 104 c->>h: ACME token 105 deactivate c 106 h->>l: send challenge response 107 deactivate h 108 deactivate sACME 109 l->>m: certificate 110 m->>c: Put(certificate) 111 deactivate l 112 end 113 m->>s: certificate 114 s->b: encrypted communication 115 deactivate m 116 deactivate s 117 118 ```