update README
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-01-12 09:41:26 +11:00
parent d087492c31
commit a3333cebb6
6 changed files with 170 additions and 57 deletions

124
README.md
View File

@@ -138,55 +138,131 @@ This operation can only be performed by a user that is a member of a group with
#### Remove User
**POST** `/api/admin/user/delete`
Data
Body
```
{
"userName": "example_username"
}
```
This operation can only be performed by a user with a role that is admin enabled. Removes user account corresponding to specified userName.
This operation can only be performed by a user that is admin enabled. Removes user account corresponding to specified userName.
#### List Users
GET `/api/admin/users`
**GET** `/api/admin/users`
This operation can only be performed by a user with a role that is admin enabled. Lists currently defined users.
This operation can only be performed by a user that is admin enabled. Lists currently defined users.
### Permission Operations
Permissions can be assigned either via a group or directly to a user Id. Permissions map the user to the safe(s) they are allowed to access. By default a permission grants read-write access to a safe, although that can be set to read-only if required.
#### List Permissions
**GET** `/api/admin/permissions`
This operation can only be performed by a user that is admin enabled. Lists currently defined permissions.
#### Create Permission
**POST** `/api/admin/permission/add`
Create a new read-only permission directly to a user
Body
```
{
"Description": "Readonly access to default safe",
"safeId": 1,
"userId": 2,
"readOnly": true
}
```
Creates a new permission mapping user/group to safe. Currently the create permission operation requires knowing the correct user Id or group Id, as well as the safe Id onto which permissions will be granted. This operation can only be performed by a user that is admin enabled.
#### Delete Permission
**POST** `/api/admin/permission/delete`
Delete permission by specifying description
Body
```
{
"Description":"Readonly access to default safe"
}
```
Delete permission by specifying permission id
Body
```
{
"permissionId":2
}
```
Deletes a permission mapping either a user or a group to a safe. Either the permission description or permission Id can be specified. This operation can only be performed by a user that is admin enabled.
Deleting a permission should be performed prior to deleting any groups specified in that permission.
### Group Operations
#### List Groups
GET `/api/admin/groups/list`
**GET** `/api/admin/groups`
This operations has not yet been implemented.
This operation can only be performed by a user with that is admin enabled. Lists currently defined groups.
This operation can only be performed by a user with a role that is admin enabled. Lists currently defined groups.
#### Create Group
**POST** `/api/admin/group/add`
### Role Operations - Deprecated
#### List Roles
GET `/api/admin/roles`
This operation can only be performed by a user with a role that is admin enabled. Lists currently defined roles.
#### Create Role
POST `/api/admin/role/add`
Data
Create a new group corresponding with an LDAP group
Body
```
{
"roleName":"example role",
"readOnly":true,
"Admin":false,
"LdapGroup":"CN=smt_users,OU=Groups,DC=example,DC=com"
"groupName":"ldap access for smt_users",
"ldapGroup":true,
"LdapDn":"CN=smt_users,OU=Groups,DC=example,DC=com"
}
```
This operation can only be performed by a user with a role that is admin enabled. Creates a new role. Can be read only, or admin enabled, or map to an LDAP group if LDAP integration is being used.
Create a new local admin group
Body
```
{
"groupName":"admin group",
"Admin":true,
Users allocated to this role will only be able to access secrets that are part of this role. The exception being users in a role with admin enabled; any user in an admin enabled role can access all secrets.
}
```
Creates a new group, which can be entirely local or mapped to an LDAP security group if LDAP integration is enabled. This operation can only be performed by a user that is admin enabled, or that is a member of a group that is admin enabled.
Ldap group must be specified via the full distinguishedName. The simplest way to get this information is to run the command `dsquery group -name <known group name>` from a windows machine.
#### Delete Group
**POST** `/api/admin/group/delete`
Delete group by specifying group name
Body
```
{
"groupName":"admin group"
}
```
Delete group by specifying group id
Body
```
{
"groupId":2
}
```
Deletes an existing group. Either group name or group Id can be specified. If both are specified, group Id takes precedence. This operation can only be performed by a user that is admin enabled, or that is a member of a group that is admin enabled.
Deleting a group will also impact all permissions based on that group. For that reason, permissions should be removed before a group is deleted.
### Secrets Operations
#### Store

View File

@@ -155,7 +155,7 @@ func AddUser(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"message": "user registration success"})
c.JSON(http.StatusOK, gin.H{"message": "user registration success", "data": u})
}
func Login(c *gin.Context) {

View File

@@ -118,18 +118,38 @@ func DeleteGroupHandler(c *gin.Context) {
g.GroupId = input.GroupId
g.GroupName = input.GroupName
if g.GroupId > 0 { // Group Id was specified
// Confirm group exists
testGroup, _ := models.GroupGetById(g.GroupId)
log.Printf("DeleteGroupHandler confirming group id '%d' exists\n", g.GroupId)
if (models.Group{} == testGroup) {
errString := fmt.Sprintf("attempt to delete non-existing group id '%d'", g.GroupId)
log.Printf("DeleteGroupHandler %s\n", errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return
}
g.GroupName = testGroup.GroupName
} else if len(g.GroupName) > 0 { // Group name was specified
//remove leading/trailing spaces in groupname
g.GroupName = html.EscapeString(strings.TrimSpace(g.GroupName))
// Confirm group exists
testGroup, _ := models.GroupGetByName(g.GroupName)
log.Printf("DeleteGroupHandler confirming group '%s' exists\n", g.GroupName)
if (models.Group{} == testGroup) {
errString := fmt.Sprintf("attempt to delete non-existing group '%s'", g.GroupName)
log.Printf("DeleteGroupHandler %s\n", errString)
c.JSON(http.StatusBadRequest, gin.H{"error": errString})
return
} else {
}
g.GroupId = testGroup.GroupId
}
// TODO verify no permissions refer to this group still
err := g.GroupDelete()
if err != nil {
@@ -140,5 +160,5 @@ func DeleteGroupHandler(c *gin.Context) {
}
c.JSON(http.StatusOK, gin.H{"message": "group deletion success"})
}
}

View File

@@ -320,7 +320,7 @@ func UpdateSecret(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"message": "secret updated successfully"})
c.JSON(http.StatusOK, gin.H{"message": "secret updated successfully", "data": models.SecretRestricted(s)})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": "multiple secrets matched search parameters, be more specific"})
return

View File

@@ -26,6 +26,19 @@ func GroupGetByName(groupname string) (Group, error) {
return g, nil
}
// GroupGetById queries the database for the specified group name
func GroupGetById(groupId int) (Group, error) {
var g Group
// Query database for matching group object
err := db.QueryRowx("SELECT * FROM groups WHERE GroupId=?", groupId).StructScan(&g)
if err != nil {
return g, errors.New("group not found")
}
return g, nil
}
// GroupGetByName queries the database for a group with the specified LDAP distinguishedName
func GroupGetByLdapDn(ldapDn string) (Group, error) {
var g Group

View File

@@ -71,7 +71,8 @@ func ReceiveKey(key string) error {
return errors.New("secret key provided is not exactly 32 bytes long")
}
// TODO hash the secret key and store it on disk so we can verify if correct secret key is received
if os.Getenv("SECRETS_KEY") == "" {
// Hash the secret key and store it on disk so we can verify if correct secret key is received
filePath, _ := getHashFilePath()
if filePath != "" && utils.FileExists(filePath) {
@@ -92,6 +93,9 @@ func ReceiveKey(key string) error {
} else {
return fmt.Errorf("unable to determine path to key hash file '%s'", hashFileName)
}
} else {
log.Printf("ReceiveKey not storing hash on disk since we read key from environment variable")
}
// Store the secret key in memory so that we can access it when encrypting/decrypting
secretKey = []byte(key)