Encrypt LDAP bind password in db with SECRET_KEY (#15547)

* Encrypt LDAP bind password in db with SECRET_KEY

The LDAP source bind password are currently stored in plaintext in the db
This PR simply encrypts them with the setting.SECRET_KEY.

Fix #15460

Signed-off-by: Andrew Thornton <art27@cantab.net>

* remove ui warning regarding unencrypted password

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
zeripath 2021-05-20 09:29:57 +01:00 committed by GitHub
parent 124b256c53
commit 17be645498
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 19 additions and 6 deletions

View file

@ -88,8 +88,8 @@ Adds the following fields:
- Bind Password (optional) - Bind Password (optional)
- The password for the Bind DN specified above, if any. _Note: The password - The password for the Bind DN specified above, if any. _Note: The password
is stored in plaintext at the server. As such, ensure that the Bind DN is stored encrypted with the SECRET_KEY on the server. It is still recommended
has as few privileges as possible._ to ensure that the Bind DN has as few privileges as possible._
- User Search Base **(required)** - User Search Base **(required)**

View file

@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/auth/oauth2" "code.gitea.io/gitea/modules/auth/oauth2"
"code.gitea.io/gitea/modules/auth/pam" "code.gitea.io/gitea/modules/auth/pam"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/secret"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -77,11 +78,25 @@ type LDAPConfig struct {
// FromDB fills up a LDAPConfig from serialized format. // FromDB fills up a LDAPConfig from serialized format.
func (cfg *LDAPConfig) FromDB(bs []byte) error { func (cfg *LDAPConfig) FromDB(bs []byte) error {
json := jsoniter.ConfigCompatibleWithStandardLibrary json := jsoniter.ConfigCompatibleWithStandardLibrary
return json.Unmarshal(bs, &cfg) err := json.Unmarshal(bs, &cfg)
if err != nil {
return err
}
if cfg.BindPasswordEncrypt != "" {
cfg.BindPassword, err = secret.DecryptSecret(setting.SecretKey, cfg.BindPasswordEncrypt)
cfg.BindPasswordEncrypt = ""
}
return err
} }
// ToDB exports a LDAPConfig to a serialized format. // ToDB exports a LDAPConfig to a serialized format.
func (cfg *LDAPConfig) ToDB() ([]byte, error) { func (cfg *LDAPConfig) ToDB() ([]byte, error) {
var err error
cfg.BindPasswordEncrypt, err = secret.EncryptSecret(setting.SecretKey, cfg.BindPassword)
if err != nil {
return nil, err
}
cfg.BindPassword = ""
json := jsoniter.ConfigCompatibleWithStandardLibrary json := jsoniter.ConfigCompatibleWithStandardLibrary
return json.Marshal(cfg) return json.Marshal(cfg)
} }

View file

@ -35,6 +35,7 @@ type Source struct {
SecurityProtocol SecurityProtocol SecurityProtocol SecurityProtocol
SkipVerify bool SkipVerify bool
BindDN string // DN to bind with BindDN string // DN to bind with
BindPasswordEncrypt string // Encrypted Bind BN password
BindPassword string // Bind DN password BindPassword string // Bind DN password
UserBase string // Base search path for users UserBase string // Base search path for users
UserDN string // Template for the DN of the user for simple auth UserDN string // Template for the DN of the user for simple auth

View file

@ -2283,7 +2283,6 @@ auths.host = Host
auths.port = Port auths.port = Port
auths.bind_dn = Bind DN auths.bind_dn = Bind DN
auths.bind_password = Bind Password auths.bind_password = Bind Password
auths.bind_password_helper = Warning: This password is stored in plain text. Use a read-only account if possible.
auths.user_base = User Search Base auths.user_base = User Search Base
auths.user_dn = User DN auths.user_dn = User DN
auths.attribute_username = Username Attribute auths.attribute_username = Username Attribute

View file

@ -53,7 +53,6 @@
<div class="field"> <div class="field">
<label for="bind_password">{{.i18n.Tr "admin.auths.bind_password"}}</label> <label for="bind_password">{{.i18n.Tr "admin.auths.bind_password"}}</label>
<input id="bind_password" name="bind_password" type="password" value="{{$cfg.BindPassword}}"> <input id="bind_password" name="bind_password" type="password" value="{{$cfg.BindPassword}}">
<p class="help text red">{{.i18n.Tr "admin.auths.bind_password_helper"}}</p>
</div> </div>
{{end}} {{end}}
<div class="{{if .Source.IsLDAP}}required{{end}} field"> <div class="{{if .Source.IsLDAP}}required{{end}} field">

View file

@ -28,7 +28,6 @@
<div class="ldap field {{if not (eq .type 2)}}hide{{end}}"> <div class="ldap field {{if not (eq .type 2)}}hide{{end}}">
<label for="bind_password">{{.i18n.Tr "admin.auths.bind_password"}}</label> <label for="bind_password">{{.i18n.Tr "admin.auths.bind_password"}}</label>
<input id="bind_password" name="bind_password" type="password" autocomplete="off" value="{{.bind_password}}"> <input id="bind_password" name="bind_password" type="password" autocomplete="off" value="{{.bind_password}}">
<p class="help text red">{{.i18n.Tr "admin.auths.bind_password_helper"}}</p>
</div> </div>
<div class="binddnrequired {{if (eq .type 2)}}required{{end}} field"> <div class="binddnrequired {{if (eq .type 2)}}required{{end}} field">
<label for="user_base">{{.i18n.Tr "admin.auths.user_base"}}</label> <label for="user_base">{{.i18n.Tr "admin.auths.user_base"}}</label>