feat(auth): implement user and device authentication
This commit is contained in:
@@ -13,6 +13,8 @@ const (
|
||||
HTTPAddressEnvironment = "CMROUBAO_HTTP_ADDR"
|
||||
DatabasePathEnvironment = "CMROUBAO_DATABASE_PATH"
|
||||
AssetDirectoryEnvironment = "CMROUBAO_ASSET_DIR"
|
||||
TLSCertificateEnvironment = "CMROUBAO_TLS_CERT_FILE"
|
||||
TLSPrivateKeyEnvironment = "CMROUBAO_TLS_KEY_FILE"
|
||||
|
||||
defaultHTTPAddress = "127.0.0.1:8080"
|
||||
defaultDatabasePath = "var/cmroubao.db"
|
||||
@@ -25,6 +27,8 @@ type Config struct {
|
||||
HTTPAddress string
|
||||
DatabasePath string
|
||||
AssetDirectory string
|
||||
TLSCertificate string
|
||||
TLSPrivateKey string
|
||||
ReadHeaderTimeout time.Duration
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
@@ -68,11 +72,39 @@ func Load(lookup LookupEnvironment) (Config, error) {
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
tlsCertificate, certificateSet, err := optionalEnvironmentValue(
|
||||
lookup,
|
||||
TLSCertificateEnvironment,
|
||||
)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
tlsPrivateKey, privateKeySet, err := optionalEnvironmentValue(
|
||||
lookup,
|
||||
TLSPrivateKeyEnvironment,
|
||||
)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
if certificateSet != privateKeySet {
|
||||
return Config{}, errors.New(
|
||||
TLSCertificateEnvironment + " and " +
|
||||
TLSPrivateKeyEnvironment + " must be set together",
|
||||
)
|
||||
}
|
||||
if !certificateSet && !isLoopbackAddress(httpAddress) {
|
||||
return Config{}, errors.New(
|
||||
HTTPAddressEnvironment +
|
||||
" must use loopback unless TLS is configured",
|
||||
)
|
||||
}
|
||||
|
||||
return Config{
|
||||
HTTPAddress: httpAddress,
|
||||
DatabasePath: filepath.Clean(databasePath),
|
||||
AssetDirectory: assetDirectory,
|
||||
TLSCertificate: cleanOptionalPath(tlsCertificate),
|
||||
TLSPrivateKey: cleanOptionalPath(tlsPrivateKey),
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
ReadTimeout: 15 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
@@ -82,6 +114,43 @@ func Load(lookup LookupEnvironment) (Config, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func cleanOptionalPath(value string) string {
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
return filepath.Clean(value)
|
||||
}
|
||||
|
||||
func optionalEnvironmentValue(
|
||||
lookup LookupEnvironment,
|
||||
name string,
|
||||
) (string, bool, error) {
|
||||
value, exists := lookup(name)
|
||||
if !exists {
|
||||
return "", false, nil
|
||||
}
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return "", false, errors.New(name + " must not be blank")
|
||||
}
|
||||
if strings.ContainsRune(value, '\x00') {
|
||||
return "", false, errors.New(name + " contains an invalid character")
|
||||
}
|
||||
return value, true, nil
|
||||
}
|
||||
|
||||
func isLoopbackAddress(address string) bool {
|
||||
host, _, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if strings.EqualFold(host, "localhost") {
|
||||
return true
|
||||
}
|
||||
ip := net.ParseIP(host)
|
||||
return ip != nil && ip.IsLoopback()
|
||||
}
|
||||
|
||||
func validatedAssetDirectory(path string) (string, error) {
|
||||
if strings.ContainsRune(path, '\x00') {
|
||||
return "", errors.New(
|
||||
|
||||
Reference in New Issue
Block a user