implement delete secret
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-01-09 15:08:11 +11:00
parent 90da2367be
commit 6423d83949
2 changed files with 94 additions and 53 deletions

View File

@@ -293,9 +293,6 @@ func UpdateSecret(c *gin.Context) {
} }
if len(secretList) == 0 { if len(secretList) == 0 {
// TODO - also check secrets allowed for user
c.JSON(http.StatusBadRequest, gin.H{"error": "no secret matching search parameters"}) c.JSON(http.StatusBadRequest, gin.H{"error": "no secret matching search parameters"})
return return
} else if len(secretList) == 1 { } else if len(secretList) == 1 {
@@ -339,77 +336,89 @@ func UpdateSecret(c *gin.Context) {
func DeleteSecret(c *gin.Context) { func DeleteSecret(c *gin.Context) {
var err error var err error
var input SecretInput var input SecretInput
var UserId int var user_id int
if err := c.ShouldBindJSON(&input); err != nil { if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON received : " + err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": "DeleteSecret error binding to input JSON : " + err.Error()})
return return
} }
// Input validation log.Printf("DeleteSecret received JSON input '%v'\n", input)
if input.DeviceCategory == "" && input.DeviceName == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "cannot store secret with empty deviceName and empty deviceCategory"}) if len(input.SecretValue) == 0 {
errString := "DeleteSecret no updated secret specified\n"
log.Print(errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return return
} }
// Temporarily disable because we should be able to figure it out without user specifying
/* /*
if input.SafeId == 0 && len(input.SafeName) == 0 { if input.SafeId == 0 && len(input.SafeName) == 0 {
errString := "StoreSecret no safe specified\n" errString := "UpdateSecret no safe specified\n"
log.Print(errString) log.Print(errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString}) c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return return
} }
*/ */
// Don't log this since it contains plaintext secrets
//log.Printf("StoreSecret received JSON input '%v'\n", input)
// Populate fields
s := models.Secret{}
s.UserName = input.UserName
s.DeviceName = input.DeviceName
s.DeviceCategory = input.DeviceCategory
// Query which safes the current user is allowed to access
/*
user_id, err := token.ExtractTokenID(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"})
return
}
*/
// Get userId that we stored in the context earlier // Get userId that we stored in the context earlier
if val, ok := c.Get("user-id"); !ok { if val, ok := c.Get("user-id"); !ok {
c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"}) c.JSON(http.StatusBadRequest, gin.H{"error": "error determining user"})
return return
} else { } else {
UserId = val.(int) user_id = val.(int)
//log.Printf("user_id: %v\n", user_id) //log.Printf("user_id: %v\n", user_id)
} }
safeId, err := FindSafeId(UserId, input) // Populate fields
s := models.Secret{}
s.UserName = input.UserName
s.DeviceName = input.DeviceName
s.DeviceCategory = input.DeviceCategory
secretList, err := models.SecretsGetAllowed(&s, user_id)
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) errString := fmt.Sprintf("error getting allowed secrets : '%s'", err)
log.Printf("DeleteSecret %s\n", errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return return
} }
s.SafeId = safeId
// If this secret already exists in the database then generate an error if len(secretList) == 0 {
checkExists, err := models.GetSecrets(&s, false) errString := "no secret matching search parameters"
if err != nil { log.Printf("DeleteSecret %s\n", errString)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return return
} } else if len(secretList) == 1 {
if len(checkExists) == 0 { // Delete secret
c.JSON(http.StatusBadRequest, gin.H{"error": "no secrets matched search parameters"}) log.Printf("secretList[0]: %v\n", secretList[0])
return
} else if len(checkExists) == 1 {
c.JSON(http.StatusOK, gin.H{"message": "mock secret deleted successfully"})
// TODO delete secret s.SecretId = secretList[0].SecretId
// check for empty fields in the update request and update from the existing record
if s.UserName == "" {
s.UserName = secretList[0].Secret.UserName
}
if s.DeviceCategory == "" {
s.DeviceCategory = secretList[0].DeviceCategory
}
if s.DeviceName == "" {
s.DeviceName = secretList[0].DeviceName
}
_, err = s.DeleteSecret()
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "DeleteSecret error deleting secret : " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "secret deleted successfully"})
} else { } else {
c.JSON(http.StatusBadRequest, gin.H{"error": "multiple secrets matched search parameters, be more specific"}) errString := "multiple secrets matched search parameters, be more specific"
log.Printf("DeleteSecret %s\n", errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return return
} }
} }

View File

@@ -95,7 +95,8 @@ func SecretsGetAllowed(s *Secret, userId int) ([]UserSecret, error) {
} }
// Query for user access // Query for user access
query += `UNION query += `
UNION
SELECT users.UserId, users.GroupId, permissions.ReadOnly, permissions.SafeId, safes.SafeName, secrets.* SELECT users.UserId, users.GroupId, permissions.ReadOnly, permissions.SafeId, safes.SafeName, secrets.*
FROM users FROM users
INNER JOIN permissions ON users.UserId = permissions.UserId INNER JOIN permissions ON users.UserId = permissions.UserId
@@ -137,16 +138,20 @@ func SecretsGetAllowed(s *Secret, userId int) ([]UserSecret, error) {
return secretResults, err return secretResults, err
} }
// Decrypt the secret /*
_, err = r.DecryptSecret() // Decrypt the secret
if err != nil { _, err = r.DecryptSecret()
//log.Printf("GetSecret unable to decrypt stored secret '%v' : '%s'\n", r.Secret, err) if err != nil {
log.Printf("SecretsGetAllowedForGroup unable to decrypt stored secret : '%s'\n", err) //log.Printf("GetSecret unable to decrypt stored secret '%v' : '%s'\n", r.Secret, err)
return secretResults, err log.Printf("SecretsGetAllowedForGroup unable to decrypt stored secret : '%s'\n", err)
} else { return secretResults, err
secretResults = append(secretResults, r) } else {
} secretResults = append(secretResults, r)
}
*/
// Don't decrypt the secrets in the results of this query
secretResults = append(secretResults, r)
} }
log.Printf("SecretsGetAllowedForGroup retrieved '%d' results\n", len(secretResults)) log.Printf("SecretsGetAllowedForGroup retrieved '%d' results\n", len(secretResults))
} }
@@ -154,6 +159,7 @@ func SecretsGetAllowed(s *Secret, userId int) ([]UserSecret, error) {
return secretResults, nil return secretResults, nil
} }
/*
func SecretsSearchAllSafes(s *Secret) ([]Secret, error) { func SecretsSearchAllSafes(s *Secret) ([]Secret, error) {
var err error var err error
var secretResults []Secret var secretResults []Secret
@@ -217,6 +223,7 @@ func SecretsSearchAllSafes(s *Secret) ([]Secret, error) {
return secretResults, nil return secretResults, nil
} }
*/
// SecretsGetMultipleSafes queries the specified safes for matching secrets // SecretsGetMultipleSafes queries the specified safes for matching secrets
func SecretsGetMultipleSafes(s *Secret, safeIds []int) ([]Secret, error) { func SecretsGetMultipleSafes(s *Secret, safeIds []int) ([]Secret, error) {
@@ -415,6 +422,31 @@ func (s *Secret) UpdateSecret() (*Secret, error) {
return s, nil return s, nil
} }
func (s *Secret) DeleteSecret() (*Secret, error) {
var err error
log.Printf("DeleteSecret deleting record with values '%v'\n", s)
if s.SecretId == 0 {
err = errors.New("unable to locate secret with empty secretId field")
log.Printf("DeleteSecret error in pre-check : '%s'\n", err)
return s, err
}
result, err := db.NamedExec((`DELETE FROM secrets WHERE SecretId = :SecretId`), s)
if err != nil {
log.Printf("DeleteSecret error executing sql record : '%s'\n", err)
return &Secret{}, err
} else {
affected, _ := result.RowsAffected()
id, _ := result.LastInsertId()
log.Printf("DeleteSecret delete returned result id '%d' affecting %d row(s).\n", id, affected)
}
return s, nil
}
// startCipher does the initial setup of the AES256 GCM mode cipher // startCipher does the initial setup of the AES256 GCM mode cipher
func startCipher() (cipher.AEAD, error) { func startCipher() (cipher.AEAD, error) {
key, err := ProvideKey() key, err := ProvideKey()