summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2019-02-03 23:56:53 +0000
committerGitHub <noreply@github.com>2019-02-03 23:56:53 +0000
commit01c10a951b9db0b9f020ef657ca71eb5e5882a84 (patch)
tree6cb29db94edda9d90e9a509028bada2a61ade928 /models
parent634cbaad2b8d091a2a3065de81e0b2b76daa5ef7 (diff)
downloadgitea-01c10a951b9db0b9f020ef657ca71eb5e5882a84.tar.gz
gitea-01c10a951b9db0b9f020ef657ca71eb5e5882a84.zip
Fix ssh deploy and user key constraints (#1357) (#5939)
1. A key can either be an ssh user key or a deploy key. It cannot be both. 2. If a key is a user key - it can only be associated with one user. 3. If a key is a deploy key - it can be used in multiple repositories and the permissions it has on those repositories can be different. 4. If a repository is deleted, its deploy keys must be deleted too. We currently don't enforce any of this and multiple repositories access with different permissions doesn't work at all. This PR enforces the following constraints: - [x] You should not be able to add the same user key as another user - [x] You should not be able to add a ssh user key which is being used as a deploy key - [x] You should not be able to add a ssh deploy key which is being used as a user key - [x] If you add an ssh deploy key to another repository you should be able to use it in different modes without losing the ability to use it in the other mode. - [x] If you delete a repository you must delete all its deploy keys. Fix #1357
Diffstat (limited to 'models')
-rw-r--r--models/repo.go17
-rw-r--r--models/ssh_key.go91
2 files changed, 73 insertions, 35 deletions
diff --git a/models/repo.go b/models/repo.go
index 5e96a4e931..873fd407fb 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -1756,6 +1756,17 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
return ErrRepoNotExist{repoID, uid, "", ""}
}
+ // Delete Deploy Keys
+ deployKeys, err := listDeployKeys(sess, repo.ID)
+ if err != nil {
+ return fmt.Errorf("listDeployKeys: %v", err)
+ }
+ for _, dKey := range deployKeys {
+ if err := deleteDeployKey(sess, doer, dKey.ID); err != nil {
+ return fmt.Errorf("deleteDeployKeys: %v", err)
+ }
+ }
+
if cnt, err := sess.ID(repoID).Delete(&Repository{}); err != nil {
return err
} else if cnt != 1 {
@@ -1898,6 +1909,12 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
}
if err = sess.Commit(); err != nil {
+ if len(deployKeys) > 0 {
+ // We need to rewrite the public keys because the commit failed
+ if err2 := RewriteAllPublicKeys(); err2 != nil {
+ return fmt.Errorf("Commit: %v SSH Keys: %v", err, err2)
+ }
+ }
return fmt.Errorf("Commit: %v", err)
}
diff --git a/models/ssh_key.go b/models/ssh_key.go
index 90c0f04b78..a7dced841d 100644
--- a/models/ssh_key.go
+++ b/models/ssh_key.go
@@ -51,7 +51,7 @@ type PublicKey struct {
ID int64 `xorm:"pk autoincr"`
OwnerID int64 `xorm:"INDEX NOT NULL"`
Name string `xorm:"NOT NULL"`
- Fingerprint string `xorm:"NOT NULL"`
+ Fingerprint string `xorm:"INDEX NOT NULL"`
Content string `xorm:"TEXT NOT NULL"`
Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
Type KeyType `xorm:"NOT NULL DEFAULT 1"`
@@ -350,7 +350,6 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
func checkKeyFingerprint(e Engine, fingerprint string) error {
has, err := e.Get(&PublicKey{
Fingerprint: fingerprint,
- Type: KeyTypeUser,
})
if err != nil {
return err
@@ -401,12 +400,18 @@ func AddPublicKey(ownerID int64, name, content string, LoginSourceID int64) (*Pu
return nil, err
}
- if err := checkKeyFingerprint(x, fingerprint); err != nil {
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
+
+ if err := checkKeyFingerprint(sess, fingerprint); err != nil {
return nil, err
}
// Key name of same user cannot be duplicated.
- has, err := x.
+ has, err := sess.
Where("owner_id = ? AND name = ?", ownerID, name).
Get(new(PublicKey))
if err != nil {
@@ -415,12 +420,6 @@ func AddPublicKey(ownerID int64, name, content string, LoginSourceID int64) (*Pu
return nil, ErrKeyNameAlreadyUsed{ownerID, name}
}
- sess := x.NewSession()
- defer sess.Close()
- if err = sess.Begin(); err != nil {
- return nil, err
- }
-
key := &PublicKey{
OwnerID: ownerID,
Name: name,
@@ -519,7 +518,7 @@ func UpdatePublicKeyUpdated(id int64) error {
}
// deletePublicKeys does the actual key deletion but does not update authorized_keys file.
-func deletePublicKeys(e *xorm.Session, keyIDs ...int64) error {
+func deletePublicKeys(e Engine, keyIDs ...int64) error {
if len(keyIDs) == 0 {
return nil
}
@@ -728,24 +727,28 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey
accessMode = AccessModeWrite
}
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
+
pkey := &PublicKey{
Fingerprint: fingerprint,
- Mode: accessMode,
- Type: KeyTypeDeploy,
}
- has, err := x.Get(pkey)
+ has, err := sess.Get(pkey)
if err != nil {
return nil, err
}
- sess := x.NewSession()
- defer sess.Close()
- if err = sess.Begin(); err != nil {
- return nil, err
- }
-
- // First time use this deploy key.
- if !has {
+ if has {
+ if pkey.Type != KeyTypeDeploy {
+ return nil, ErrKeyAlreadyExist{0, fingerprint, ""}
+ }
+ } else {
+ // First time use this deploy key.
+ pkey.Mode = accessMode
+ pkey.Type = KeyTypeDeploy
pkey.Content = content
pkey.Name = name
if err = addKey(sess, pkey); err != nil {
@@ -763,8 +766,12 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey
// GetDeployKeyByID returns deploy key by given ID.
func GetDeployKeyByID(id int64) (*DeployKey, error) {
+ return getDeployKeyByID(x, id)
+}
+
+func getDeployKeyByID(e Engine, id int64) (*DeployKey, error) {
key := new(DeployKey)
- has, err := x.ID(id).Get(key)
+ has, err := e.ID(id).Get(key)
if err != nil {
return nil, err
} else if !has {
@@ -775,11 +782,15 @@ func GetDeployKeyByID(id int64) (*DeployKey, error) {
// GetDeployKeyByRepo returns deploy key by given public key ID and repository ID.
func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) {
+ return getDeployKeyByRepo(x, keyID, repoID)
+}
+
+func getDeployKeyByRepo(e Engine, keyID, repoID int64) (*DeployKey, error) {
key := &DeployKey{
KeyID: keyID,
RepoID: repoID,
}
- has, err := x.Get(key)
+ has, err := e.Get(key)
if err != nil {
return nil, err
} else if !has {
@@ -802,7 +813,19 @@ func UpdateDeployKey(key *DeployKey) error {
// DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed.
func DeleteDeployKey(doer *User, id int64) error {
- key, err := GetDeployKeyByID(id)
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ if err := deleteDeployKey(sess, doer, id); err != nil {
+ return err
+ }
+ return sess.Commit()
+}
+
+func deleteDeployKey(sess Engine, doer *User, id int64) error {
+ key, err := getDeployKeyByID(sess, id)
if err != nil {
if IsErrDeployKeyNotExist(err) {
return nil
@@ -812,11 +835,11 @@ func DeleteDeployKey(doer *User, id int64) error {
// Check if user has access to delete this key.
if !doer.IsAdmin {
- repo, err := GetRepositoryByID(key.RepoID)
+ repo, err := getRepositoryByID(sess, key.RepoID)
if err != nil {
return fmt.Errorf("GetRepositoryByID: %v", err)
}
- has, err := IsUserRepoAdmin(repo, doer)
+ has, err := isUserRepoAdmin(sess, repo, doer)
if err != nil {
return fmt.Errorf("GetUserRepoPermission: %v", err)
} else if !has {
@@ -824,12 +847,6 @@ func DeleteDeployKey(doer *User, id int64) error {
}
}
- sess := x.NewSession()
- defer sess.Close()
- if err = sess.Begin(); err != nil {
- return err
- }
-
if _, err = sess.ID(key.ID).Delete(new(DeployKey)); err != nil {
return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err)
}
@@ -851,13 +868,17 @@ func DeleteDeployKey(doer *User, id int64) error {
}
}
- return sess.Commit()
+ return nil
}
// ListDeployKeys returns all deploy keys by given repository ID.
func ListDeployKeys(repoID int64) ([]*DeployKey, error) {
+ return listDeployKeys(x, repoID)
+}
+
+func listDeployKeys(e Engine, repoID int64) ([]*DeployKey, error) {
keys := make([]*DeployKey, 0, 5)
- return keys, x.
+ return keys, e.
Where("repo_id = ?", repoID).
Find(&keys)
}