|
|
|
@@ -2,6 +2,7 @@ package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/sha256"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
@@ -174,8 +175,6 @@ const (
|
|
|
|
|
nginxObservabilityPortPlaceholder = "__OPENFLARE_OBSERVABILITY_PORT__"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const basicAuthSupportDir = "basic_auth"
|
|
|
|
|
|
|
|
|
|
var requiredMainConfigTemplatePlaceholders = []string{
|
|
|
|
|
"{{OpenRestyWorkerProcesses}}",
|
|
|
|
|
"{{OpenRestyWorkerConnections}}",
|
|
|
|
@@ -937,19 +936,11 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
|
|
|
|
LimitRate: route.LimitRate,
|
|
|
|
|
}
|
|
|
|
|
upstreamConfig := buildRouteUpstreamConfig(route, upstreams)
|
|
|
|
|
basicAuthFilePath := ""
|
|
|
|
|
if route.BasicAuthEnabled {
|
|
|
|
|
basicAuthFilePath = buildBasicAuthSupportFilePath(route)
|
|
|
|
|
supportFiles = append(supportFiles, SupportFile{
|
|
|
|
|
Path: basicAuthFilePath,
|
|
|
|
|
Content: renderBasicAuthSupportFile(route.BasicAuthUsername, route.BasicAuthPassword),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if upstreamConfig.UsesNamedUpstream {
|
|
|
|
|
builder.WriteString(renderNamedUpstreamBlock(upstreamConfig))
|
|
|
|
|
}
|
|
|
|
|
if !route.EnableHTTPS {
|
|
|
|
|
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, basicAuthFilePath, cfg))
|
|
|
|
|
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
certIDs, err := decodeStoredCertIDs(route.CertIDs, route.CertID)
|
|
|
|
@@ -1010,7 +1001,7 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
|
|
|
|
|
|
|
|
|
if route.RedirectHTTP {
|
|
|
|
|
if len(httpOnlyDomains) > 0 {
|
|
|
|
|
builder.WriteString(renderHTTPProxyServer(renderServerNames(httpOnlyDomains), route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, basicAuthFilePath, cfg))
|
|
|
|
|
builder.WriteString(renderHTTPProxyServer(renderServerNames(httpOnlyDomains), route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
|
|
|
|
}
|
|
|
|
|
for _, certID := range certIDs {
|
|
|
|
|
assignedDomains := domainsByCertID[certID]
|
|
|
|
@@ -1020,14 +1011,14 @@ func renderRouteConfig(routes []*model.ProxyRoute, cfg openRestyConfigSnapshot)
|
|
|
|
|
builder.WriteString(renderHTTPRedirectServer(renderServerNames(assignedDomains)))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, basicAuthFilePath, cfg))
|
|
|
|
|
builder.WriteString(renderHTTPProxyServer(serverNames, route.OriginURL, route.OriginHost, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
|
|
|
|
}
|
|
|
|
|
for _, certID := range certIDs {
|
|
|
|
|
assignedDomains := domainsByCertID[certID]
|
|
|
|
|
if len(assignedDomains) == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
builder.WriteString(renderHTTPSServer(renderServerNames(assignedDomains), route.OriginURL, route.OriginHost, certID, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, basicAuthFilePath, cfg))
|
|
|
|
|
builder.WriteString(renderHTTPSServer(renderServerNames(assignedDomains), route.OriginURL, route.OriginHost, certID, customHeaders, cacheConfig, limitConfig, upstreamConfig, route.PoWEnabled, route.BasicAuthEnabled, route.BasicAuthUsername, route.BasicAuthPassword, cfg))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return builder.String(), dedupeSupportFiles(supportFiles), nil
|
|
|
|
@@ -1143,15 +1134,20 @@ func renderPowAccessBlock(powEnabled bool) string {
|
|
|
|
|
return fmt.Sprintf(" access_by_lua_file %s/pow/check.lua;\n", nginxLuaDirPlaceholder)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderBasicAuthBlock(filePath string) string {
|
|
|
|
|
if strings.TrimSpace(filePath) == "" {
|
|
|
|
|
func renderBasicAuthBlock(enabled bool, username, password string) string {
|
|
|
|
|
if !enabled || username == "" || password == "" {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf(" auth_basic \"Restricted\";\n auth_basic_user_file %s/%s;\n", nginxCertDirPlaceholder, filePath)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderBasicAuthSupportFile(username, password string) string {
|
|
|
|
|
return fmt.Sprintf("%s:{PLAIN}%s\n", username, password)
|
|
|
|
|
credentials := username + ":" + password
|
|
|
|
|
encoded := base64.StdEncoding.EncodeToString([]byte(credentials))
|
|
|
|
|
return fmt.Sprintf(` rewrite_by_lua_block {
|
|
|
|
|
local auth = ngx.var.http_authorization
|
|
|
|
|
if auth ~= "Basic %s" then
|
|
|
|
|
ngx.header["WWW-Authenticate"] = 'Basic realm="Restricted"'
|
|
|
|
|
return ngx.exit(401)
|
|
|
|
|
end
|
|
|
|
|
}
|
|
|
|
|
`, encoded)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderPowLocationBlocks(powEnabled bool) string {
|
|
|
|
@@ -1281,21 +1277,21 @@ func nextVersionNumber(now time.Time) (string, error) {
|
|
|
|
|
return fmt.Sprintf("%s-%03d", prefix, count+1), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderHTTPProxyServer(serverNames string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthFilePath string, cfg openRestyConfigSnapshot) string {
|
|
|
|
|
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, renderPowAccessBlock(powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthFilePath), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
|
|
|
|
func renderHTTPProxyServer(serverNames string, originURL string, originHost string, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg openRestyConfigSnapshot) string {
|
|
|
|
|
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, renderPowAccessBlock(powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderHTTPRedirectServer(serverNames string) string {
|
|
|
|
|
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n\n return 301 https://$host$request_uri;\n}\n\n", serverNames)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderHTTPSServer(serverNames string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthFilePath string, cfg openRestyConfigSnapshot) string {
|
|
|
|
|
func renderHTTPSServer(serverNames string, originURL string, originHost string, certificateID uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg openRestyConfigSnapshot) string {
|
|
|
|
|
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
|
|
|
|
keyPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateKeyFileName(certificateID))
|
|
|
|
|
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, certPath, keyPath, renderPowAccessBlock(powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthFilePath), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
|
|
|
|
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, certPath, keyPath, renderPowAccessBlock(powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderHTTPSServerWithCertificates(serverNames string, originURL string, originHost string, certificateIDs []uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthFilePath string, cfg openRestyConfigSnapshot) string {
|
|
|
|
|
func renderHTTPSServerWithCertificates(serverNames string, originURL string, originHost string, certificateIDs []uint, customHeaders []ProxyRouteCustomHeaderInput, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg openRestyConfigSnapshot) string {
|
|
|
|
|
var certificateBlock strings.Builder
|
|
|
|
|
for _, certificateID := range certificateIDs {
|
|
|
|
|
certPath := fmt.Sprintf("%s/%s", nginxCertDirPlaceholder, certificateCertFileName(certificateID))
|
|
|
|
@@ -1303,7 +1299,7 @@ func renderHTTPSServerWithCertificates(serverNames string, originURL string, ori
|
|
|
|
|
certificateBlock.WriteString(fmt.Sprintf(" ssl_certificate %s;\n", certPath))
|
|
|
|
|
certificateBlock.WriteString(fmt.Sprintf(" ssl_certificate_key %s;\n", keyPath))
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n%s%s%s\n location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, certificateBlock.String(), renderPowAccessBlock(powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthFilePath), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
|
|
|
|
return fmt.Sprintf("server {\n listen 443 ssl;\n http2 on;\n server_name %s;\n%s%s%s\n location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, certificateBlock.String(), renderPowAccessBlock(powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderServerNames(domains []string) string {
|
|
|
|
@@ -1595,10 +1591,6 @@ func buildRouteUpstreamName(route *model.ProxyRoute) string {
|
|
|
|
|
return fmt.Sprintf("backend_%s_%d", sanitized, route.ID)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildBasicAuthSupportFilePath(route *model.ProxyRoute) string {
|
|
|
|
|
return fmt.Sprintf("%s/%s.htpasswd", basicAuthSupportDir, buildRouteUpstreamName(route))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func renderNamedUpstreamBlock(upstreamConfig routeUpstreamConfig) string {
|
|
|
|
|
var builder strings.Builder
|
|
|
|
|
builder.WriteString(fmt.Sprintf("upstream %s {\n", upstreamConfig.Name))
|
|
|
|
|