mirror of
https://github.com/passbolt/go-passbolt.git
synced 2025-09-13 06:19:08 +00:00
Move code from Internal Git
This commit is contained in:
parent
4457df3e5f
commit
ff29c83d56
26 changed files with 2008 additions and 0 deletions
33
helper/folder.go
Normal file
33
helper/folder.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/speatzle/go-passbolt"
|
||||
)
|
||||
|
||||
func CreateFolder(ctx context.Context, c *passbolt.Client, folderParentID, name string) (string, error) {
|
||||
f, err := c.CreateFolder(ctx, passbolt.Folder{
|
||||
Name: name,
|
||||
FolderParentID: folderParentID,
|
||||
})
|
||||
return f.ID, err
|
||||
}
|
||||
|
||||
func GetFolder(ctx context.Context, c *passbolt.Client, folderID string) (string, string, error) {
|
||||
f, err := c.GetFolder(ctx, folderID)
|
||||
return f.FolderParentID, f.Name, err
|
||||
}
|
||||
|
||||
func UpdateFolder(ctx context.Context, c *passbolt.Client, folderID, name string) error {
|
||||
_, err := c.UpdateFolder(ctx, folderID, passbolt.Folder{Name: name})
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteFolder(ctx context.Context, c *passbolt.Client, folderID string) error {
|
||||
return c.DeleteFolder(ctx, folderID)
|
||||
}
|
||||
|
||||
func MoveFolder(ctx context.Context, c *passbolt.Client, folderID, folderParentID string) error {
|
||||
return c.MoveFolder(ctx, folderID, folderParentID)
|
||||
}
|
208
helper/resources.go
Normal file
208
helper/resources.go
Normal file
|
@ -0,0 +1,208 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/speatzle/go-passbolt"
|
||||
)
|
||||
|
||||
// CreateResource Creates a Resource where the Password and Description are Encrypted and Returns the Resources ID
|
||||
func CreateResource(ctx context.Context, c *passbolt.Client, folderParentID, name, username, uri, password, description string) (string, error) {
|
||||
types, err := c.GetResourceTypes(ctx, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Getting ResourceTypes: %w", err)
|
||||
}
|
||||
var rType *passbolt.ResourceType
|
||||
for _, tmp := range types {
|
||||
if tmp.Slug == "password-and-description" {
|
||||
rType = &tmp
|
||||
}
|
||||
}
|
||||
if rType == nil {
|
||||
return "", fmt.Errorf("Cannot find Resource type password-and-description")
|
||||
}
|
||||
|
||||
resource := passbolt.Resource{
|
||||
ResourceTypeID: rType.ID,
|
||||
FolderParentID: folderParentID,
|
||||
Name: name,
|
||||
Username: username,
|
||||
URI: uri,
|
||||
}
|
||||
|
||||
tmp := passbolt.SecretDataTypePasswordAndDescription{
|
||||
Password: password,
|
||||
Description: description,
|
||||
}
|
||||
secretData, err := json.Marshal(&tmp)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Marshalling Secret Data: %w", err)
|
||||
}
|
||||
|
||||
encSecretData, err := c.EncryptMessage(string(secretData))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Encrypting Secret Data for User me: %w", err)
|
||||
}
|
||||
resource.Secrets = []passbolt.Secret{{Data: encSecretData}}
|
||||
|
||||
newresource, err := c.CreateResource(ctx, resource)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Creating Resource: %w", err)
|
||||
}
|
||||
return newresource.ID, nil
|
||||
}
|
||||
|
||||
// CreateResourceSimple Creates a Legacy Resource where only the Password is Encrypted and Returns the Resources ID
|
||||
func CreateResourceSimple(ctx context.Context, c *passbolt.Client, folderParentID, name, username, uri, password, description string) (string, error) {
|
||||
enc, err := c.EncryptMessage(password)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Encrypting Password: %w", err)
|
||||
}
|
||||
|
||||
res := passbolt.Resource{
|
||||
Name: name,
|
||||
URI: uri,
|
||||
Username: username,
|
||||
FolderParentID: folderParentID,
|
||||
Description: description,
|
||||
Secrets: []passbolt.Secret{
|
||||
{Data: enc},
|
||||
},
|
||||
}
|
||||
|
||||
resource, err := c.CreateResource(ctx, res)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Creating Resource: %w", err)
|
||||
}
|
||||
return resource.ID, nil
|
||||
}
|
||||
|
||||
// GetResource Gets a Resource by ID
|
||||
func GetResource(ctx context.Context, c *passbolt.Client, resourceID string) (folderParentID, name, username, uri, password, description string, err error) {
|
||||
resource, err := c.GetResource(ctx, resourceID)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", "", fmt.Errorf("Getting Resource: %w", err)
|
||||
}
|
||||
|
||||
rType, err := c.GetResourceType(ctx, resource.ResourceTypeID)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", "", fmt.Errorf("Getting ResourceType: %w", err)
|
||||
}
|
||||
secret, err := c.GetSecret(ctx, resource.ID)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", "", fmt.Errorf("Getting Resource Secret: %w", err)
|
||||
}
|
||||
var pw string
|
||||
var desc string
|
||||
switch rType.Slug {
|
||||
case "password-string":
|
||||
pw, err = c.DecryptMessage(secret.Data)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
|
||||
}
|
||||
desc = resource.Description
|
||||
case "password-and-description":
|
||||
rawSecretData, err := c.DecryptMessage(secret.Data)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", "", fmt.Errorf("Decrypting Secret Data: %w", err)
|
||||
}
|
||||
|
||||
var secretData passbolt.SecretDataTypePasswordAndDescription
|
||||
err = json.Unmarshal([]byte(rawSecretData), &secretData)
|
||||
if err != nil {
|
||||
return "", "", "", "", "", "", fmt.Errorf("Parsing Decrypted Secret Data: %w", err)
|
||||
}
|
||||
pw = secretData.Password
|
||||
desc = secretData.Description
|
||||
default:
|
||||
return "", "", "", "", "", "", fmt.Errorf("Unknown ResourceType: %v", rType.Slug)
|
||||
}
|
||||
return resource.FolderParentID, resource.Name, resource.Username, resource.URI, pw, desc, nil
|
||||
}
|
||||
|
||||
// UpdateResource Updates all Fields.
|
||||
// Note if you want to Change the FolderParentID please use the MoveResource Function
|
||||
func UpdateResource(ctx context.Context, c *passbolt.Client, resourceID, name, username, uri, password, description string) error {
|
||||
resource, err := c.GetResource(ctx, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Resource: %w", err)
|
||||
}
|
||||
|
||||
rType, err := c.GetResourceType(ctx, resource.ResourceTypeID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting ResourceType: %w", err)
|
||||
}
|
||||
|
||||
opts := &passbolt.GetUsersOptions{
|
||||
FilterHasAccess: resourceID,
|
||||
}
|
||||
users, err := c.GetUsers(ctx, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Users: %w", err)
|
||||
}
|
||||
|
||||
newResource := passbolt.Resource{
|
||||
ID: resourceID,
|
||||
// This needs to be specified or it will revert to a legacy password
|
||||
ResourceTypeID: resource.ResourceTypeID,
|
||||
Name: name,
|
||||
Username: username,
|
||||
URI: uri,
|
||||
}
|
||||
|
||||
var secretData string
|
||||
switch rType.Slug {
|
||||
case "password-string":
|
||||
newResource.Description = description
|
||||
secretData = password
|
||||
case "password-and-description":
|
||||
tmp := passbolt.SecretDataTypePasswordAndDescription{
|
||||
Password: password,
|
||||
Description: description,
|
||||
}
|
||||
res, err := json.Marshal(&tmp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Marshalling Secret Data: %w", err)
|
||||
}
|
||||
secretData = string(res)
|
||||
default:
|
||||
return fmt.Errorf("Unknown ResourceType: %v", rType.Slug)
|
||||
}
|
||||
|
||||
newResource.Secrets = []passbolt.Secret{}
|
||||
for _, user := range users {
|
||||
var encSecretData string
|
||||
// if this is our user use our stored and verified public key instead
|
||||
if user.ID == c.GetUserID() {
|
||||
encSecretData, err = c.EncryptMessage(secretData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Encrypting Secret Data for User me: %w", err)
|
||||
}
|
||||
} else {
|
||||
encSecretData, err = c.EncryptMessageWithPublicKey(user.GPGKey.ArmoredKey, secretData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Encrypting Secret Data for User %v: %w", user.ID, err)
|
||||
}
|
||||
}
|
||||
newResource.Secrets = append(newResource.Secrets, passbolt.Secret{
|
||||
UserID: user.ID,
|
||||
Data: encSecretData,
|
||||
})
|
||||
}
|
||||
|
||||
_, err = c.UpdateResource(ctx, resourceID, newResource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Updating Resource: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteResource(ctx context.Context, c *passbolt.Client, resourceID string) error {
|
||||
return c.DeleteResource(ctx, resourceID)
|
||||
}
|
||||
|
||||
func MoveResource(ctx context.Context, c *passbolt.Client, resourceID, folderParentID string) error {
|
||||
return c.MoveResource(ctx, resourceID, folderParentID)
|
||||
}
|
218
helper/share.go
Normal file
218
helper/share.go
Normal file
|
@ -0,0 +1,218 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/speatzle/go-passbolt"
|
||||
)
|
||||
|
||||
// ShareOperation defines how Resources are to be Shared With Users/Groups
|
||||
type ShareOperation struct {
|
||||
// Type of Permission: 1 = Read, 7 = can Update, 15 = Owner (Owner can also Share Resource)
|
||||
// Note: Setting this to -1 Will delete this Permission if it already Exists, errors if this Permission Dosen't Already Exists
|
||||
Type int
|
||||
// ARO is what Type this should be Shared With (User, Group)
|
||||
ARO string
|
||||
// AROID is the ID of the User or Group(ARO) this should be Shared With
|
||||
AROID string
|
||||
}
|
||||
|
||||
// ShareResourceWithUsersAndGroups Shares a Resource With The Users and Groups with the Specified Permission Type,
|
||||
// if the Resource has already been shared With the User/Group the Permission Type will be Adjusted/Deleted
|
||||
func ShareResourceWithUsersAndGroups(ctx context.Context, c *passbolt.Client, resourceID string, Users []string, Groups []string, permissionType int) error {
|
||||
changes := []ShareOperation{}
|
||||
for _, userID := range Users {
|
||||
changes = append(changes, ShareOperation{
|
||||
Type: permissionType,
|
||||
ARO: "User",
|
||||
AROID: userID,
|
||||
})
|
||||
}
|
||||
for _, groupID := range Groups {
|
||||
changes = append(changes, ShareOperation{
|
||||
Type: permissionType,
|
||||
ARO: "Group",
|
||||
AROID: groupID,
|
||||
})
|
||||
}
|
||||
return ShareResource(ctx, c, resourceID, changes)
|
||||
}
|
||||
|
||||
// ShareResource Shares a Resource as Specified in the Passed ShareOperation Struct Slice
|
||||
func ShareResource(ctx context.Context, c *passbolt.Client, resourceID string, changes []ShareOperation) error {
|
||||
oldPermissions, err := c.GetResourcePermissions(ctx, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Resource Permissions: %w", err)
|
||||
}
|
||||
|
||||
permissionChanges, err := GeneratePermissionChanges(oldPermissions, changes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Generating Resource Permission Changes: %w", err)
|
||||
}
|
||||
|
||||
shareRequest := passbolt.ResourceShareRequest{Permissions: permissionChanges}
|
||||
|
||||
secret, err := c.GetSecret(ctx, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Get Resource: %w", err)
|
||||
}
|
||||
|
||||
secretData, err := c.DecryptMessage(secret.Data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Decrypting Resource Secret: %w", err)
|
||||
}
|
||||
|
||||
simulationResult, err := c.SimulateShareResource(ctx, resourceID, shareRequest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Simulate Share Resource: %w", err)
|
||||
}
|
||||
|
||||
users, err := c.GetUsers(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Get Users: %w", err)
|
||||
}
|
||||
|
||||
shareRequest.Secrets = []passbolt.Secret{}
|
||||
for _, user := range simulationResult.Changes.Added {
|
||||
pubkey, err := getPublicKeyByUserID(user.User.ID, users)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Public Key for User %v: %w", user.User.ID, err)
|
||||
}
|
||||
|
||||
encSecretData, err := c.EncryptMessageWithPublicKey(pubkey, secretData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Encrypting Secret for User %v: %w", user.User.ID, err)
|
||||
}
|
||||
shareRequest.Secrets = append(shareRequest.Secrets, passbolt.Secret{
|
||||
UserID: user.User.ID,
|
||||
Data: encSecretData,
|
||||
})
|
||||
}
|
||||
|
||||
err = c.ShareResource(ctx, resourceID, shareRequest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Sharing Resource: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShareFolderWithUsersAndGroups Shares a Folder With The Users and Groups with the Specified Type,
|
||||
// if the Folder has already been shared With the User/Group the Permission Type will be Adjusted/Deleted.
|
||||
// Note: Resources Permissions in the Folder are not Adjusted (Like the Extention does)
|
||||
func ShareFolderWithUsersAndGroups(ctx context.Context, c *passbolt.Client, folderID string, Users []string, Groups []string, permissionType int) error {
|
||||
changes := []ShareOperation{}
|
||||
for _, userID := range Users {
|
||||
changes = append(changes, ShareOperation{
|
||||
Type: permissionType,
|
||||
ARO: "User",
|
||||
AROID: userID,
|
||||
})
|
||||
}
|
||||
for _, groupID := range Groups {
|
||||
changes = append(changes, ShareOperation{
|
||||
Type: permissionType,
|
||||
ARO: "Group",
|
||||
AROID: groupID,
|
||||
})
|
||||
}
|
||||
return ShareFolder(ctx, c, folderID, changes)
|
||||
}
|
||||
|
||||
// ShareFolder Shares a Folder as Specified in the Passed ShareOperation Struct Slice.
|
||||
// Note Resources Permissions in the Folder are not Adjusted
|
||||
func ShareFolder(ctx context.Context, c *passbolt.Client, folderID string, changes []ShareOperation) error {
|
||||
oldPermissions, err := c.GetFolderPermissions(ctx, folderID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Folder Permissions: %w", err)
|
||||
}
|
||||
|
||||
permissionChanges, err := GeneratePermissionChanges(oldPermissions, changes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Generating Folder Permission Changes: %w", err)
|
||||
}
|
||||
|
||||
err = c.ShareFolder(ctx, folderID, permissionChanges)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Sharing Folder: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GeneratePermissionChanges Generates the Permission Changes for a Resource/Folder nessesary for a single Share Operation
|
||||
func GeneratePermissionChanges(oldPermissions []passbolt.Permission, changes []ShareOperation) ([]passbolt.Permission, error) {
|
||||
// Check for Duplicate Users/Groups as that would break stuff
|
||||
for i, changeA := range changes {
|
||||
for j, changeB := range changes {
|
||||
if i != j && changeA.AROID == changeB.AROID && changeA.ARO == changeB.ARO {
|
||||
return nil, fmt.Errorf("Change %v and %v are Both About the same ARO %v ID: %v, there can only be once change per ARO", i, j, changeA.ARO, changeA.AROID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get ACO and ACO ID from Existing Permissions
|
||||
if len(oldPermissions) == 0 {
|
||||
return nil, fmt.Errorf("There has to be atleast one Permission on a ACO")
|
||||
}
|
||||
ACO := oldPermissions[0].ACO
|
||||
ACOID := oldPermissions[0].ACOForeignKey
|
||||
|
||||
permissionChanges := []passbolt.Permission{}
|
||||
for _, change := range changes {
|
||||
// Find Permission thats invloves the Same ARO as Requested in the change
|
||||
var oldPermission *passbolt.Permission
|
||||
for _, oldPerm := range oldPermissions {
|
||||
if oldPerm.ARO == change.ARO && oldPerm.AROForeignKey == change.AROID {
|
||||
oldPermission = &oldPerm
|
||||
}
|
||||
}
|
||||
// Check Wheter Matching Permission Already Exists and needs to be adjusted or is a new one can be created
|
||||
if oldPermission == nil {
|
||||
if change.Type == 15 || change.Type == 7 || change.Type == 1 {
|
||||
permissionChanges = append(permissionChanges, passbolt.Permission{
|
||||
IsNew: true,
|
||||
Type: change.Type,
|
||||
ARO: change.ARO,
|
||||
AROForeignKey: change.AROID,
|
||||
ACO: ACO,
|
||||
ACOForeignKey: ACOID,
|
||||
})
|
||||
} else if change.Type == -1 {
|
||||
return nil, fmt.Errorf("Permission for %v %v Cannot be Deleted as No Matching Permission Exists", change.ARO, change.AROID)
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unknown Permission Type: %v", change.Type)
|
||||
}
|
||||
} else {
|
||||
tmp := passbolt.Permission{
|
||||
ID: oldPermission.ID,
|
||||
ARO: change.ARO,
|
||||
AROForeignKey: change.AROID,
|
||||
ACO: ACO,
|
||||
ACOForeignKey: ACOID,
|
||||
}
|
||||
|
||||
if change.Type == 15 || change.Type == 7 || change.Type == 1 {
|
||||
if oldPermission.Type == change.Type {
|
||||
return nil, fmt.Errorf("Permission for %v %v is already Type %v", change.ARO, change.AROID, change.Type)
|
||||
}
|
||||
tmp.Type = change.Type
|
||||
} else if change.Type == -1 {
|
||||
tmp.Delete = true
|
||||
tmp.Type = oldPermission.Type
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unknown Permission Type: %v", change.Type)
|
||||
}
|
||||
permissionChanges = append(permissionChanges, tmp)
|
||||
}
|
||||
}
|
||||
return permissionChanges, nil
|
||||
}
|
||||
|
||||
func getPublicKeyByUserID(userID string, Users []passbolt.User) (string, error) {
|
||||
for _, user := range Users {
|
||||
if user.ID == userID {
|
||||
return user.GPGKey.ArmoredKey, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("Cannot Find Key for user id %v", userID)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue