Implement v5 Resource Creation

This commit is contained in:
Samuel Lorch 2025-05-12 20:02:51 +02:00
parent 5369030d50
commit e90a19a41d

View file

@ -5,11 +5,144 @@ import (
"encoding/json"
"fmt"
"github.com/ProtonMail/gopenpgp/v3/crypto"
"github.com/passbolt/go-passbolt/api"
)
// CreateResource Creates a Resource where the Password and Description are Encrypted and Returns the Resources ID
// CreateResource Creates a Resource, Creates a v4 or v5 Resources based on the server Preference
func CreateResource(ctx context.Context, c *api.Client, folderParentID, name, username, uri, password, description string) (string, error) {
// Create a v5 Password if that is the Server Default
if c.MetadataTypeSettings().DefaultResourceType == api.PassboltAPIVersionTypeV5 {
return CreateResourceV5(ctx, c, folderParentID, name, username, uri, password, description)
} else {
return CreateResourceV4(ctx, c, folderParentID, name, username, uri, password, description)
}
}
func CreateResourceV5(ctx context.Context, c *api.Client, folderParentID, name, username, uri, password, description string) (string, error) {
if c.MetadataTypeSettings().AllowCreationOfV5Resources == false {
return "", fmt.Errorf("Creation of V5 Passwords is disabled on this Server")
}
types, err := c.GetResourceTypes(ctx, nil)
if err != nil {
return "", fmt.Errorf("Getting ResourceTypes: %w", err)
}
var rType *api.ResourceType
for _, tmp := range types {
if tmp.Slug == "v5-default" {
rType = &tmp
break
}
}
if rType == nil {
return "", fmt.Errorf("Cannot find Resource type password-and-description")
}
// Base Resource
resource := api.Resource{
ResourceTypeID: rType.ID,
FolderParentID: folderParentID,
}
// Resource Metadata
meta := api.ResourceMetadataTypeV5Default{
ObjectType: api.PASSBOLT_OBJECT_TYPE_RESOURCE_METADATA,
Name: name,
Username: username,
URIs: []string{uri},
}
metaData, err := json.Marshal(&meta)
if err != nil {
return "", fmt.Errorf("Marshalling metadata: %w", err)
}
err = validateMetadata(rType, string(metaData))
if err != nil {
return "", fmt.Errorf("Validating metadata: %w", err)
}
var publicMetadataKey *crypto.Key
// Since we are not sharing, use the Personal Key if allowed
if c.MetadataKeySettings().AllowUsageOfPersonalKeys {
publicMetadataKey, err = c.GetUserPrivateKeyCopy()
if err != nil {
return "", fmt.Errorf("Get User Private Key: %w", err)
}
me, err := c.GetMe(ctx)
if err != nil {
return "", fmt.Errorf("Get User Me: %w", err)
}
if me.GPGKey == nil {
return "", fmt.Errorf("User Me GPG Key nil")
}
resource.MetadataKeyID = me.GPGKey.ID
resource.MetadataKeyType = api.MetadataKeyTypeUserKey
} else {
keys, err := c.GetMetadataKeys(ctx, nil)
if err != nil {
return "", fmt.Errorf("Get Metadata Key: %w", err)
}
// TODO Get Key by id?
if len(keys) != 1 {
return "", fmt.Errorf("Not Exactly One Metadatakey Available")
}
publicMetadataKey, err = crypto.NewKeyFromArmored(keys[0].ArmoredKey)
if err != nil {
return "", fmt.Errorf("Get Metadata Public Key: %w", err)
}
resource.MetadataKeyID = keys[0].ID
resource.MetadataKeyType = api.MetadataKeyTypeSharedKey
}
encMetadata, err := c.EncryptMessageWithKey(publicMetadataKey, string(metaData))
if err != nil {
return "", fmt.Errorf("Encrypt Metadata: %w", err)
}
resource.Metadata = encMetadata
// Resource Secret
secret := api.SecretDataTypeV5Default{
ObjectType: api.PASSBOLT_OBJECT_TYPE_SECRET_DATA,
Password: password,
Description: description,
}
secretData, err := json.Marshal(&secret)
if err != nil {
return "", fmt.Errorf("Marshalling Secret Data: %w", err)
}
err = validateSecretData(rType, string(secretData))
if err != nil {
return "", fmt.Errorf("Validating 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 = []api.Secret{{Data: encSecretData}}
newresource, err := c.CreateResource(ctx, resource)
if err != nil {
return "", fmt.Errorf("Creating Resource: %w", err)
}
return newresource.ID, nil
}
func CreateResourceV4(ctx context.Context, c *api.Client, folderParentID, name, username, uri, password, description string) (string, error) {
if c.MetadataTypeSettings().AllowCreationOfV4Resources == false {
return "", fmt.Errorf("Creation of V4 Passwords is disabled on this Server")
}
types, err := c.GetResourceTypes(ctx, nil)
if err != nil {
return "", fmt.Errorf("Getting ResourceTypes: %w", err)
@ -62,6 +195,12 @@ func CreateResource(ctx context.Context, c *api.Client, folderParentID, name, us
// CreateResourceSimple Creates a Legacy Resource where only the Password is Encrypted and Returns the Resources ID
func CreateResourceSimple(ctx context.Context, c *api.Client, folderParentID, name, username, uri, password, description string) (string, error) {
if c.MetadataTypeSettings().AllowCreationOfV4Resources == false {
return "", fmt.Errorf("Creation of V4 Passwords is disabled on this Server")
}
// TODO Create a v5-password-string if v5 is enabled
enc, err := c.EncryptMessage(password)
if err != nil {
return "", fmt.Errorf("Encrypting Password: %w", err)