Skip to content

Commit 1c88349

Browse files
committed
Make only externally managed keys disabled
Signed-off-by: Andrew Thornton <[email protected]>
1 parent 029e05f commit 1c88349

File tree

5 files changed

+98
-88
lines changed

5 files changed

+98
-88
lines changed

models/ssh_key.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,82 @@ func deletePublicKeys(e Engine, keyIDs ...int64) error {
661661
return err
662662
}
663663

664+
// PublicKeysAreExternallyManaged returns whether the provided KeyID represents an externally managed Key
665+
func PublicKeysAreExternallyManaged(keys []*PublicKey) ([]bool, error) {
666+
sources := make([]*LoginSource, 0, 5)
667+
externals := make([]bool, len(keys))
668+
keyloop:
669+
for i, key := range keys {
670+
if key.LoginSourceID == 0 {
671+
externals[i] = false
672+
continue keyloop
673+
}
674+
675+
var source *LoginSource
676+
677+
sourceloop:
678+
for _, s := range sources {
679+
if s.ID == key.LoginSourceID {
680+
source = s
681+
break sourceloop
682+
}
683+
}
684+
685+
if source == nil {
686+
var err error
687+
source, err = GetLoginSourceByID(key.LoginSourceID)
688+
if err != nil {
689+
if IsErrLoginSourceNotExist(err) {
690+
externals[i] = false
691+
sources[i] = &LoginSource{
692+
ID: key.LoginSourceID,
693+
}
694+
continue keyloop
695+
}
696+
return nil, err
697+
}
698+
}
699+
700+
ldapSource := source.LDAP()
701+
if ldapSource != nil &&
702+
source.IsSyncEnabled &&
703+
(source.Type == LoginLDAP || source.Type == LoginDLDAP) &&
704+
len(strings.TrimSpace(ldapSource.AttributeSSHPublicKey)) > 0 {
705+
// Disable setting SSH keys for this user
706+
externals[i] = true
707+
}
708+
}
709+
710+
return externals, nil
711+
}
712+
713+
// PublicKeyIsExternallyManaged returns whether the provided KeyID represents an externally managed Key
714+
func PublicKeyIsExternallyManaged(id int64) (bool, error) {
715+
key, err := GetPublicKeyByID(id)
716+
if err != nil {
717+
return false, err
718+
}
719+
if key.LoginSourceID == 0 {
720+
return false, nil
721+
}
722+
source, err := GetLoginSourceByID(key.LoginSourceID)
723+
if err != nil {
724+
if IsErrLoginSourceNotExist(err) {
725+
return false, nil
726+
}
727+
return false, err
728+
}
729+
ldapSource := source.LDAP()
730+
if ldapSource != nil &&
731+
source.IsSyncEnabled &&
732+
(source.Type == LoginLDAP || source.Type == LoginDLDAP) &&
733+
len(strings.TrimSpace(ldapSource.AttributeSSHPublicKey)) > 0 {
734+
// Disable setting SSH keys for this user
735+
return true, nil
736+
}
737+
return false, nil
738+
}
739+
664740
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
665741
func DeletePublicKey(doer *User, id int64) (err error) {
666742
key, err := GetPublicKeyByID(id)

options/locale/locale_en-US.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ principal_state_desc = This principal has been used in the last 7 days
556556
show_openid = Show on profile
557557
hide_openid = Hide from profile
558558
ssh_disabled = SSH Disabled
559-
ssh_externally_managed = SSH keys are externally managed for this user
559+
ssh_externally_managed = This SSH key is externally managed for this user
560560
manage_social = Manage Associated Social Accounts
561561
social_desc = These social accounts are linked to your Gitea account. Make sure you recognize all of them as they can be used to sign in to your Gitea account.
562562
unbind = Unlink

routers/api/v1/user/key.go

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package user
66

77
import (
88
"net/http"
9-
"strings"
109

1110
"code.gitea.io/gitea/models"
1211
"code.gitea.io/gitea/modules/context"
@@ -202,25 +201,6 @@ func GetPublicKey(ctx *context.APIContext) {
202201
ctx.JSON(http.StatusOK, apiKey)
203202
}
204203

205-
func sshKeysExternallyManaged(user *models.User) (bool, error) {
206-
if user.LoginSource == 0 {
207-
return false, nil
208-
}
209-
source, err := models.GetLoginSourceByID(user.LoginSource)
210-
if err != nil {
211-
return false, err
212-
}
213-
ldapSource := source.LDAP()
214-
if ldapSource != nil &&
215-
source.IsSyncEnabled &&
216-
(source.Type == models.LoginLDAP || source.Type == models.LoginDLDAP) &&
217-
len(strings.TrimSpace(ldapSource.AttributeSSHPublicKey)) > 0 {
218-
// Disable setting SSH keys for this user
219-
return true, nil
220-
}
221-
return false, nil
222-
}
223-
224204
// CreateUserPublicKey creates new public key to given user by ID.
225205
func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid int64) {
226206
content, err := models.CheckPublicKeyString(form.Key)
@@ -229,18 +209,6 @@ func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid
229209
return
230210
}
231211

232-
user, err := models.GetUserByID(uid)
233-
if err != nil {
234-
ctx.Error(http.StatusInternalServerError, "GetUserByID", err)
235-
}
236-
externallyManaged, err := sshKeysExternallyManaged(user)
237-
if err != nil {
238-
ctx.Error(http.StatusInternalServerError, "sshKeysExternallyManaged", err)
239-
}
240-
if externallyManaged {
241-
ctx.Error(http.StatusForbidden, "", "SSH Keys are externally managed for this user")
242-
}
243-
244212
key, err := models.AddPublicKey(uid, form.Title, content, 0)
245213
if err != nil {
246214
repo.HandleAddKeyError(ctx, err)
@@ -298,15 +266,17 @@ func DeletePublicKey(ctx *context.APIContext) {
298266
// "$ref": "#/responses/forbidden"
299267
// "404":
300268
// "$ref": "#/responses/notFound"
301-
externallyManaged, err := sshKeysExternallyManaged(ctx.User)
269+
270+
id := ctx.ParamsInt64(":id")
271+
externallyManaged, err := models.PublicKeyIsExternallyManaged(id)
302272
if err != nil {
303-
ctx.Error(http.StatusInternalServerError, "sshKeysExternallyManaged", err)
273+
ctx.Error(http.StatusInternalServerError, "PublicKeyIsExternallyManaged", err)
304274
}
305275
if externallyManaged {
306-
ctx.Error(http.StatusForbidden, "", "SSH Keys are externally managed for this user")
276+
ctx.Error(http.StatusForbidden, "", "SSH Key is externally managed for this user")
307277
}
308278

309-
if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
279+
if err := models.DeletePublicKey(ctx.User, id); err != nil {
310280
if models.IsErrKeyNotExist(err) {
311281
ctx.NotFound()
312282
} else if models.IsErrKeyAccessDenied(err) {

routers/user/setting/keys.go

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
package setting
77

88
import (
9-
"strings"
10-
119
"code.gitea.io/gitea/models"
1210
"code.gitea.io/gitea/modules/auth"
1311
"code.gitea.io/gitea/modules/base"
@@ -32,25 +30,6 @@ func Keys(ctx *context.Context) {
3230
ctx.HTML(200, tplSettingsKeys)
3331
}
3432

35-
func sshKeysExternallyManaged(user *models.User) (bool, error) {
36-
if user.LoginSource == 0 {
37-
return false, nil
38-
}
39-
source, err := models.GetLoginSourceByID(user.LoginSource)
40-
if err != nil {
41-
return false, err
42-
}
43-
ldapSource := source.LDAP()
44-
if ldapSource != nil &&
45-
source.IsSyncEnabled &&
46-
(source.Type == models.LoginLDAP || source.Type == models.LoginDLDAP) &&
47-
len(strings.TrimSpace(ldapSource.AttributeSSHPublicKey)) > 0 {
48-
// Disable setting SSH keys for this user
49-
return true, nil
50-
}
51-
return false, nil
52-
}
53-
5433
// KeysPost response for change user's SSH/GPG keys
5534
func KeysPost(ctx *context.Context, form auth.AddKeyForm) {
5635
ctx.Data["Title"] = ctx.Tr("settings")
@@ -126,16 +105,6 @@ func KeysPost(ctx *context.Context, form auth.AddKeyForm) {
126105
ctx.Flash.Success(ctx.Tr("settings.add_gpg_key_success", keyIDs))
127106
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
128107
case "ssh":
129-
external, err := sshKeysExternallyManaged(ctx.User)
130-
if err != nil {
131-
ctx.ServerError("sshKeysExternalManaged", err)
132-
return
133-
}
134-
if external {
135-
ctx.Flash.Error(ctx.Tr("setting.ssh_externally_managed"))
136-
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
137-
return
138-
}
139108
content, err := models.CheckPublicKeyString(form.Content)
140109
if err != nil {
141110
if models.IsErrSSHDisabled(err) {
@@ -191,7 +160,8 @@ func DeleteKey(ctx *context.Context) {
191160
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
192161
}
193162
case "ssh":
194-
external, err := sshKeysExternallyManaged(ctx.User)
163+
keyID := ctx.QueryInt64("id")
164+
external, err := models.PublicKeyIsExternallyManaged(keyID)
195165
if err != nil {
196166
ctx.ServerError("sshKeysExternalManaged", err)
197167
return
@@ -201,7 +171,7 @@ func DeleteKey(ctx *context.Context) {
201171
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
202172
return
203173
}
204-
if err := models.DeletePublicKey(ctx.User, ctx.QueryInt64("id")); err != nil {
174+
if err := models.DeletePublicKey(ctx.User, keyID); err != nil {
205175
ctx.Flash.Error("DeletePublicKey: " + err.Error())
206176
} else {
207177
ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
@@ -222,21 +192,19 @@ func DeleteKey(ctx *context.Context) {
222192
}
223193

224194
func loadKeysData(ctx *context.Context) {
225-
external, err := sshKeysExternallyManaged(ctx.User)
195+
keys, err := models.ListPublicKeys(ctx.User.ID, models.ListOptions{})
226196
if err != nil {
227-
ctx.ServerError("sshKeysExternalManaged", err)
197+
ctx.ServerError("ListPublicKeys", err)
228198
return
229199
}
230-
if external {
231-
ctx.Data["SSHKeysExternalManaged"] = true
232-
}
200+
ctx.Data["Keys"] = keys
233201

234-
keys, err := models.ListPublicKeys(ctx.User.ID, models.ListOptions{})
202+
externalKeys, err := models.PublicKeysAreExternallyManaged(keys)
235203
if err != nil {
236204
ctx.ServerError("ListPublicKeys", err)
237205
return
238206
}
239-
ctx.Data["Keys"] = keys
207+
ctx.Data["ExternalKeys"] = externalKeys
240208

241209
gpgkeys, err := models.ListGPGKeys(ctx.User.ID, models.ListOptions{})
242210
if err != nil {

templates/user/settings/keys_ssh.tmpl

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
<h4 class="ui top attached header">
22
{{.i18n.Tr "settings.manage_ssh_keys"}}
33
<div class="ui right">
4-
{{if not ( or .DisableSSH .SSHKeysExternalManaged ) }}
4+
{{if not .DisableSSH }}
55
<div class="ui blue tiny show-panel button" data-panel="#add-ssh-key-panel">{{.i18n.Tr "settings.add_key"}}</div>
6-
{{else if .SSHKeysExternalManaged}}
7-
<div class="ui blue tiny button disabled">{{.i18n.Tr "settings.ssh_externally_managed"}}</div>
86
{{else}}
97
<div class="ui blue tiny button disabled">{{.i18n.Tr "settings.ssh_disabled"}}</div>
108
{{end}}
@@ -15,15 +13,13 @@
1513
<div class="item">
1614
{{.i18n.Tr "settings.ssh_desc"}}
1715
</div>
18-
{{range .Keys}}
16+
{{range $index, $key := .Keys}}
1917
<div class="item">
20-
{{if not $.SSHKeysExternalManaged}}
21-
<div class="right floated content">
22-
<button class="ui red tiny button delete-button" id="delete-ssh" data-url="{{$.Link}}/delete?type=ssh" data-id="{{.ID}}">
23-
{{$.i18n.Tr "settings.delete_key"}}
24-
</button>
25-
</div>
26-
{{end}}
18+
<div class="right floated content">
19+
<button class="ui red tiny button delete-button{{if index $.ExternalKeys $index}} disabled{{end}}" id="delete-ssh" data-url="{{$.Link}}/delete?type=ssh" data-id="{{.ID}}"{{if index $.ExternalKeys $index}} title="{{$.i18n.Tr "settings.ssh_externally_managed"}}"{{end}}>
20+
{{$.i18n.Tr "settings.delete_key"}}
21+
</button>
22+
</div>
2723
<div class="left floated content">
2824
<span class="{{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.i18n.Tr "settings.key_state_desc"}}" data-variation="inverted tiny"{{end}}>{{svg "octicon-key" 32}}</span>
2925
</div>

0 commit comments

Comments
 (0)