github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/internal/env/cert.go (about) 1 package env 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "os" 8 "path/filepath" 9 "regexp" 10 "strings" 11 ) 12 13 const ( 14 defaultDomain = "127.0.0.1" 15 defaultCertFile = "fullchain.pem" 16 defaultKeyFile = "privkey.pem" 17 ) 18 19 // Domain returns the domain name where quickfeed will be served. 20 // Domain should not include the server name. 21 func Domain() string { 22 domain := os.Getenv("DOMAIN") 23 if domain == "" { 24 domain = defaultDomain 25 } 26 return domain 27 } 28 29 // WhiteList returns a list of domains that the server will create certificates for. 30 func Whitelist() ([]string, error) { 31 domains := os.Getenv("QUICKFEED_WHITELIST") 32 if domains == "" { 33 return nil, errors.New("required whitelist is undefined") 34 } 35 if regexp.MustCompile(`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`).MatchString(domains) { 36 return nil, errors.New("whitelist contains IP addresses") 37 } 38 // Split domains by comma and remove whitespace and empty entries 39 domainList := make([]string, 0) 40 for _, domain := range strings.Split(strings.ReplaceAll(domains, " ", ""), ",") { 41 if domain == "" { 42 continue 43 } 44 if IsLocal(domain) { 45 return nil, fmt.Errorf("whitelist contains local/private domain: %s", domain) 46 } 47 domainList = append(domainList, domain) 48 } 49 if len(domainList) == 0 { 50 return nil, errors.New("required whitelist is undefined") 51 } 52 return domainList, nil 53 } 54 55 // CertFile returns the full path to the certificate file. 56 // To specify a different file, use the QUICKFEED_CERT_FILE environment variable. 57 func CertFile() string { 58 certFile := os.Getenv("QUICKFEED_CERT_FILE") 59 if certFile == "" { 60 // If cert file is not specified, use the default cert file. 61 certFile = filepath.Join(CertPath(), Domain(), defaultCertFile) 62 } 63 return certFile 64 } 65 66 // KeyFile returns the full path to the certificate key file. 67 // To specify a different key, use the QUICKFEED_KEY_FILE environment variable. 68 func KeyFile() string { 69 keyFile := os.Getenv("QUICKFEED_KEY_FILE") 70 if keyFile == "" { 71 // If cert key is not specified, use the default cert key. 72 keyFile = filepath.Join(CertPath(), Domain(), defaultKeyFile) 73 } 74 return keyFile 75 } 76 77 // CertPath returns the full path to the directory containing the certificates. 78 // If QUICKFEED_CERT_PATH is not set, the default path $QUICKFEED/internal/config/certs is used. 79 func CertPath() string { 80 certPath := os.Getenv("QUICKFEED_CERT_PATH") 81 if certPath == "" { 82 certPath = filepath.Join(Root(), "internal", "config", "certs") 83 } 84 return certPath 85 } 86 87 func IsLocal(domain string) bool { 88 ips, err := net.LookupIP(domain) 89 if err != nil { 90 return false 91 } 92 for _, ip := range ips { 93 if !(ip.IsLoopback() || ip.IsPrivate()) { 94 return false 95 } 96 } 97 return true 98 }