0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2024-12-22 23:33:15 -05:00
forgejo/modules/setting/config_env.go

171 lines
4.7 KiB
Go
Raw Permalink Normal View History

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"bytes"
"os"
"regexp"
"strconv"
"strings"
"code.gitea.io/gitea/modules/log"
)
const (
[BRANDING] parse FORGEJO__* in the container environment (cherry picked from commit b0759917479ee17ccb11773176dbc8a75323c5cb) (cherry picked from commit da3f76228e24d2276784ad7e1a03a34d094750e0) (cherry picked from commit 20d196e74f9d7827cd812e3eb714eb87e888b6db) (cherry picked from commit 0bf8b1824eac416ddb40fd2e0d7605573ba087a3) (cherry picked from commit 655bb770a7cf65ada5d3e214ec23219e6cb19df0) (cherry picked from commit d69d5c2c46f00b041beeb67a6238c5193ce9710a) (cherry picked from commit 00b55e5a5396a49a6798a3ae2588e412637a77c6) (cherry picked from commit 456121fd8a4c0c30f7854bd04907f2a0a583d27f) (cherry picked from commit 9716a158e48ad6333f46fc0806a838603606e5ea) (cherry picked from commit 7d60a6f5116124b72927a52db0dd36af7a9c3621) (cherry picked from commit d32a6d9437a38ac35320ad7329eece1ab2bd54d1) (cherry picked from commit ee1de38527ea1fbd52c319cfbbca24deef951fc1) (cherry picked from commit 54e7799d13fa041be172d4a05d036cee43e390d4) (cherry picked from commit 4f04da7ab716ccb1f2816842cde62965e89a852a) (cherry picked from commit 0d39a0a520c80abdc955e93cf2470eeb01d52496) (cherry picked from commit 7d8ae8279f350763c5ca04b462b288331656f53b) (cherry picked from commit 76b6770b73026e5192cc118363d8154242a5c7fc) (cherry picked from commit 9bc0d960640e589fbb0560dea379e9b90543a5a2) Conflicts: contrib/environment-to-ini/environment-to-ini.go https://codeberg.org/forgejo/forgejo/pulls/1769 (cherry picked from commit e21bf9b1446ee1eb78f29f037243239acab6a340) (cherry picked from commit 96e501c5f038eebd04f0e0e466b8b4ccca769310) (cherry picked from commit 466a66a1f6d22694a6fc9d99378f91ad8cf66d87) (cherry picked from commit 7814cf700af5f9812ab7294b03faeef00c23ef76) (cherry picked from commit 4d12344871d882c6dd2cfa5b34383d06ad77e562) (cherry picked from commit fad4cf84c3b6f4891006154549faedd603267bbd) (cherry picked from commit 7ad89400ee90b3c45072c175a40d9c77fbc0fb36) (cherry picked from commit ec911404471fc8092e6b733a7cee41a518a360a5) (cherry picked from commit 295a7f4487b72914eb0c47ded1c41f620bdd4245) (cherry picked from commit 66163a5dcfead59b7f0962c7c0ad9dad15dfa300) (cherry picked from commit 9e06f57269fb7ebe38161adfe6fa584c0e23c46e)
2023-07-10 16:17:39 -05:00
EnvConfigKeyPrefixGitea = "^(FORGEJO|GITEA)__"
EnvConfigKeySuffixFile = "__FILE"
)
const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_"
var escapeRegex = regexp.MustCompile(escapeRegexpString)
func CollectEnvConfigKeys() (keys []string) {
for _, env := range os.Environ() {
if strings.HasPrefix(env, EnvConfigKeyPrefixGitea) {
k, _, _ := strings.Cut(env, "=")
keys = append(keys, k)
}
}
return keys
}
func ClearEnvConfigKeys() {
for _, k := range CollectEnvConfigKeys() {
_ = os.Unsetenv(k)
}
}
// decodeEnvSectionKey will decode a portable string encoded Section__Key pair
// Portable strings are considered to be of the form [A-Z0-9_]*
// We will encode a disallowed value as the UTF8 byte string preceded by _0X and
// followed by _. E.g. _0X2C_ for a '-' and _0X2E_ for '.'
// Section and Key are separated by a plain '__'.
// The entire section can be encoded as a UTF8 byte string
func decodeEnvSectionKey(encoded string) (ok bool, section, key string) {
inKey := false
last := 0
escapeStringIndices := escapeRegex.FindAllStringIndex(encoded, -1)
for _, unescapeIdx := range escapeStringIndices {
preceding := encoded[last:unescapeIdx[0]]
if !inKey {
if splitter := strings.Index(preceding, "__"); splitter > -1 {
section += preceding[:splitter]
inKey = true
key += preceding[splitter+2:]
} else {
section += preceding
}
} else {
key += preceding
}
toDecode := encoded[unescapeIdx[0]+3 : unescapeIdx[1]-1]
decodedBytes := make([]byte, len(toDecode)/2)
for i := 0; i < len(toDecode)/2; i++ {
// Can ignore error here as we know these should be hexadecimal from the regexp
byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 0)
decodedBytes[i] = byte(byteInt)
}
if inKey {
key += string(decodedBytes)
} else {
section += string(decodedBytes)
}
last = unescapeIdx[1]
}
remaining := encoded[last:]
if !inKey {
if splitter := strings.Index(remaining, "__"); splitter > -1 {
section += remaining[:splitter]
key += remaining[splitter+2:]
} else {
section += remaining
}
} else {
key += remaining
}
section = strings.ToLower(section)
ok = key != ""
if !ok {
section = ""
key = ""
}
return ok, section, key
}
// decodeEnvironmentKey decode the environment key to section and key
// The environment key is in the form of GITEA__SECTION__KEY or GITEA__SECTION__KEY__FILE
func decodeEnvironmentKey(prefixRegexp *regexp.Regexp, suffixFile, envKey string) (ok bool, section, key string, useFileValue bool) { //nolint:unparam
if strings.HasSuffix(envKey, suffixFile) {
useFileValue = true
envKey = envKey[:len(envKey)-len(suffixFile)]
}
[BRANDING] parse FORGEJO__* in the container environment (cherry picked from commit b0759917479ee17ccb11773176dbc8a75323c5cb) (cherry picked from commit da3f76228e24d2276784ad7e1a03a34d094750e0) (cherry picked from commit 20d196e74f9d7827cd812e3eb714eb87e888b6db) (cherry picked from commit 0bf8b1824eac416ddb40fd2e0d7605573ba087a3) (cherry picked from commit 655bb770a7cf65ada5d3e214ec23219e6cb19df0) (cherry picked from commit d69d5c2c46f00b041beeb67a6238c5193ce9710a) (cherry picked from commit 00b55e5a5396a49a6798a3ae2588e412637a77c6) (cherry picked from commit 456121fd8a4c0c30f7854bd04907f2a0a583d27f) (cherry picked from commit 9716a158e48ad6333f46fc0806a838603606e5ea) (cherry picked from commit 7d60a6f5116124b72927a52db0dd36af7a9c3621) (cherry picked from commit d32a6d9437a38ac35320ad7329eece1ab2bd54d1) (cherry picked from commit ee1de38527ea1fbd52c319cfbbca24deef951fc1) (cherry picked from commit 54e7799d13fa041be172d4a05d036cee43e390d4) (cherry picked from commit 4f04da7ab716ccb1f2816842cde62965e89a852a) (cherry picked from commit 0d39a0a520c80abdc955e93cf2470eeb01d52496) (cherry picked from commit 7d8ae8279f350763c5ca04b462b288331656f53b) (cherry picked from commit 76b6770b73026e5192cc118363d8154242a5c7fc) (cherry picked from commit 9bc0d960640e589fbb0560dea379e9b90543a5a2) Conflicts: contrib/environment-to-ini/environment-to-ini.go https://codeberg.org/forgejo/forgejo/pulls/1769 (cherry picked from commit e21bf9b1446ee1eb78f29f037243239acab6a340) (cherry picked from commit 96e501c5f038eebd04f0e0e466b8b4ccca769310) (cherry picked from commit 466a66a1f6d22694a6fc9d99378f91ad8cf66d87) (cherry picked from commit 7814cf700af5f9812ab7294b03faeef00c23ef76) (cherry picked from commit 4d12344871d882c6dd2cfa5b34383d06ad77e562) (cherry picked from commit fad4cf84c3b6f4891006154549faedd603267bbd) (cherry picked from commit 7ad89400ee90b3c45072c175a40d9c77fbc0fb36) (cherry picked from commit ec911404471fc8092e6b733a7cee41a518a360a5) (cherry picked from commit 295a7f4487b72914eb0c47ded1c41f620bdd4245) (cherry picked from commit 66163a5dcfead59b7f0962c7c0ad9dad15dfa300) (cherry picked from commit 9e06f57269fb7ebe38161adfe6fa584c0e23c46e)
2023-07-10 16:17:39 -05:00
loc := prefixRegexp.FindStringIndex(envKey)
if loc == nil {
return false, "", "", false
}
ok, section, key = decodeEnvSectionKey(envKey[loc[1]:])
return ok, section, key, useFileValue
}
func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
[BRANDING] parse FORGEJO__* in the container environment (cherry picked from commit b0759917479ee17ccb11773176dbc8a75323c5cb) (cherry picked from commit da3f76228e24d2276784ad7e1a03a34d094750e0) (cherry picked from commit 20d196e74f9d7827cd812e3eb714eb87e888b6db) (cherry picked from commit 0bf8b1824eac416ddb40fd2e0d7605573ba087a3) (cherry picked from commit 655bb770a7cf65ada5d3e214ec23219e6cb19df0) (cherry picked from commit d69d5c2c46f00b041beeb67a6238c5193ce9710a) (cherry picked from commit 00b55e5a5396a49a6798a3ae2588e412637a77c6) (cherry picked from commit 456121fd8a4c0c30f7854bd04907f2a0a583d27f) (cherry picked from commit 9716a158e48ad6333f46fc0806a838603606e5ea) (cherry picked from commit 7d60a6f5116124b72927a52db0dd36af7a9c3621) (cherry picked from commit d32a6d9437a38ac35320ad7329eece1ab2bd54d1) (cherry picked from commit ee1de38527ea1fbd52c319cfbbca24deef951fc1) (cherry picked from commit 54e7799d13fa041be172d4a05d036cee43e390d4) (cherry picked from commit 4f04da7ab716ccb1f2816842cde62965e89a852a) (cherry picked from commit 0d39a0a520c80abdc955e93cf2470eeb01d52496) (cherry picked from commit 7d8ae8279f350763c5ca04b462b288331656f53b) (cherry picked from commit 76b6770b73026e5192cc118363d8154242a5c7fc) (cherry picked from commit 9bc0d960640e589fbb0560dea379e9b90543a5a2) Conflicts: contrib/environment-to-ini/environment-to-ini.go https://codeberg.org/forgejo/forgejo/pulls/1769 (cherry picked from commit e21bf9b1446ee1eb78f29f037243239acab6a340) (cherry picked from commit 96e501c5f038eebd04f0e0e466b8b4ccca769310) (cherry picked from commit 466a66a1f6d22694a6fc9d99378f91ad8cf66d87) (cherry picked from commit 7814cf700af5f9812ab7294b03faeef00c23ef76) (cherry picked from commit 4d12344871d882c6dd2cfa5b34383d06ad77e562) (cherry picked from commit fad4cf84c3b6f4891006154549faedd603267bbd) (cherry picked from commit 7ad89400ee90b3c45072c175a40d9c77fbc0fb36) (cherry picked from commit ec911404471fc8092e6b733a7cee41a518a360a5) (cherry picked from commit 295a7f4487b72914eb0c47ded1c41f620bdd4245) (cherry picked from commit 66163a5dcfead59b7f0962c7c0ad9dad15dfa300) (cherry picked from commit 9e06f57269fb7ebe38161adfe6fa584c0e23c46e)
2023-07-10 16:17:39 -05:00
prefixRegexp := regexp.MustCompile(EnvConfigKeyPrefixGitea)
for _, kv := range envs {
idx := strings.IndexByte(kv, '=')
if idx < 0 {
continue
}
// parse the environment variable to config section name and key name
envKey := kv[:idx]
envValue := kv[idx+1:]
[BRANDING] parse FORGEJO__* in the container environment (cherry picked from commit b0759917479ee17ccb11773176dbc8a75323c5cb) (cherry picked from commit da3f76228e24d2276784ad7e1a03a34d094750e0) (cherry picked from commit 20d196e74f9d7827cd812e3eb714eb87e888b6db) (cherry picked from commit 0bf8b1824eac416ddb40fd2e0d7605573ba087a3) (cherry picked from commit 655bb770a7cf65ada5d3e214ec23219e6cb19df0) (cherry picked from commit d69d5c2c46f00b041beeb67a6238c5193ce9710a) (cherry picked from commit 00b55e5a5396a49a6798a3ae2588e412637a77c6) (cherry picked from commit 456121fd8a4c0c30f7854bd04907f2a0a583d27f) (cherry picked from commit 9716a158e48ad6333f46fc0806a838603606e5ea) (cherry picked from commit 7d60a6f5116124b72927a52db0dd36af7a9c3621) (cherry picked from commit d32a6d9437a38ac35320ad7329eece1ab2bd54d1) (cherry picked from commit ee1de38527ea1fbd52c319cfbbca24deef951fc1) (cherry picked from commit 54e7799d13fa041be172d4a05d036cee43e390d4) (cherry picked from commit 4f04da7ab716ccb1f2816842cde62965e89a852a) (cherry picked from commit 0d39a0a520c80abdc955e93cf2470eeb01d52496) (cherry picked from commit 7d8ae8279f350763c5ca04b462b288331656f53b) (cherry picked from commit 76b6770b73026e5192cc118363d8154242a5c7fc) (cherry picked from commit 9bc0d960640e589fbb0560dea379e9b90543a5a2) Conflicts: contrib/environment-to-ini/environment-to-ini.go https://codeberg.org/forgejo/forgejo/pulls/1769 (cherry picked from commit e21bf9b1446ee1eb78f29f037243239acab6a340) (cherry picked from commit 96e501c5f038eebd04f0e0e466b8b4ccca769310) (cherry picked from commit 466a66a1f6d22694a6fc9d99378f91ad8cf66d87) (cherry picked from commit 7814cf700af5f9812ab7294b03faeef00c23ef76) (cherry picked from commit 4d12344871d882c6dd2cfa5b34383d06ad77e562) (cherry picked from commit fad4cf84c3b6f4891006154549faedd603267bbd) (cherry picked from commit 7ad89400ee90b3c45072c175a40d9c77fbc0fb36) (cherry picked from commit ec911404471fc8092e6b733a7cee41a518a360a5) (cherry picked from commit 295a7f4487b72914eb0c47ded1c41f620bdd4245) (cherry picked from commit 66163a5dcfead59b7f0962c7c0ad9dad15dfa300) (cherry picked from commit 9e06f57269fb7ebe38161adfe6fa584c0e23c46e)
2023-07-10 16:17:39 -05:00
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixRegexp, EnvConfigKeySuffixFile, envKey)
if !ok {
continue
}
// use environment value as config value, or read the file content as value if the key indicates a file
keyValue := envValue
if useFileValue {
fileContent, err := os.ReadFile(envValue)
if err != nil {
log.Error("Error reading file for %s : %v", envKey, envValue, err)
continue
}
if bytes.HasSuffix(fileContent, []byte("\r\n")) {
fileContent = fileContent[:len(fileContent)-2]
} else if bytes.HasSuffix(fileContent, []byte("\n")) {
fileContent = fileContent[:len(fileContent)-1]
}
keyValue = string(fileContent)
}
// try to set the config value if necessary
section, err := cfg.GetSection(sectionName)
if err != nil {
section, err = cfg.NewSection(sectionName)
if err != nil {
log.Error("Error creating section: %s : %v", sectionName, err)
continue
}
}
key := ConfigSectionKey(section, keyName)
if key == nil {
changed = true
key, err = section.NewKey(keyName, keyValue)
if err != nil {
log.Error("Error creating key: %s in section: %s with value: %s : %v", keyName, sectionName, keyValue, err)
continue
}
}
oldValue := key.Value()
if !changed && oldValue != keyValue {
changed = true
}
key.SetValue(keyValue)
}
return changed
}