go-passbolt/helper/resource_create.go

193 lines
5.5 KiB
Go

package helper
import (
"context"
"encoding/json"
"fmt"
"github.com/passbolt/go-passbolt/api"
)
// 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,
ResourceTypeID: rType.ID,
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)
}
metadataKeyID, metadataKeyType, publicMetadataKey, err := GetMetadataKey(ctx, c, true)
if err != nil {
return "", fmt.Errorf("Get Metadata Key: %w", err)
}
resource.MetadataKeyID = metadataKeyID
resource.MetadataKeyType = metadataKeyType
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)
}
var rType *api.ResourceType
for _, tmp := range types {
if tmp.Slug == "password-and-description" {
rType = &tmp
break
}
}
if rType == nil {
return "", fmt.Errorf("Cannot find Resource type password-and-description")
}
resource := api.Resource{
ResourceTypeID: rType.ID,
FolderParentID: folderParentID,
Name: name,
Username: username,
URI: uri,
}
tmp := api.SecretDataTypePasswordAndDescription{
Password: password,
Description: description,
}
secretData, err := json.Marshal(&tmp)
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
}
// 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)
}
res := api.Resource{
Name: name,
URI: uri,
Username: username,
FolderParentID: folderParentID,
Description: description,
Secrets: []api.Secret{
{Data: enc},
},
}
resource, err := c.CreateResource(ctx, res)
if err != nil {
return "", fmt.Errorf("Creating Resource: %w", err)
}
return resource.ID, nil
}