Merge pull request #44 from passbolt/v5-basic-metadatakeys
Some checks failed
Go / test (push) Has been cancelled

V5 basic metadatakeys
This commit is contained in:
Samuel Lorch 2025-03-14 13:35:44 +01:00 committed by GitHub
commit 5ce336e200
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 209 additions and 14 deletions

View file

@ -26,12 +26,22 @@ type APIHeader struct {
}
// DoCustomRequest Executes a Custom Request and returns a APIResponse
//
// Deprecated: DoCustomRequest is deprecated. Use DoCustomRequestV5 instead
func (c *Client) DoCustomRequest(ctx context.Context, method, path, version string, body interface{}, opts interface{}) (*APIResponse, error) {
_, response, err := c.DoCustomRequestAndReturnRawResponse(ctx, method, path, version, body, opts)
return response, err
}
// DoCustomRequestV5 Executes a Custom Request and returns a APIResponse
func (c *Client) DoCustomRequestV5(ctx context.Context, method, path string, body interface{}, opts interface{}) (*APIResponse, error) {
_, response, err := c.DoCustomRequestAndReturnRawResponseV5(ctx, method, path, body, opts)
return response, err
}
// DoCustomRequestAndReturnRawResponse Executes a Custom Request and returns a APIResponse and the Raw HTTP Response
//
// Deprecated: DoCustomRequestAndReturnRawResponse is deprecated. Use DoCustomRequestAndReturnRawResponseV5 instead
func (c *Client) DoCustomRequestAndReturnRawResponse(ctx context.Context, method, path, version string, body interface{}, opts interface{}) (*http.Response, *APIResponse, error) {
// version is no longer used and is ignored.
return c.DoCustomRequestAndReturnRawResponseV5(ctx, method, path, body, opts)

19
api/foreign_model.go Normal file
View file

@ -0,0 +1,19 @@
package api
type ForeignModelTypes string
const (
ForeignModelTypesResource ForeignModelTypes = "Resource"
ForeignModelTypesSecret ForeignModelTypes = "Secret"
ForeignModelTypesFolder = "Folder"
ForeignModelTypesComment = "Comment"
ForeignModelTypesTag = "Tag"
)
func (s ForeignModelTypes) IsValid() bool {
switch s {
case ForeignModelTypesResource, ForeignModelTypesSecret, ForeignModelTypesFolder, ForeignModelTypesComment, ForeignModelTypesTag:
return true
}
return false
}

View file

@ -0,0 +1,61 @@
package api
import (
"context"
"encoding/json"
"fmt"
)
// MetadataSessionKey is a MetadataSessionKey
type MetadataSessionKey struct {
ID string `json:"id,omitempty"`
UserID string `json:"user_id,omitempty"`
Data string `json:"data,omitempty"`
Created Time `json:"created,omitempty"`
Modified Time `json:"modified,omitempty"`
}
// MetadataSessionKeyData is a MetadataSessionKeyData
type MetadataSessionKeyData struct {
// ObjectType Must always be PASSBOLT_SESSION_KEYS
ObjectType string `json:"object_type,omitempty"`
SessionKeys []MetadataSessionKeyDataElement `json:"session_keys,omitempty"`
}
// MetadataSessionKeyDataElement is a MetadataSessionKeyDataElement
type MetadataSessionKeyDataElement struct {
ForeignModel ForeignModelTypes `json:"foreign_model"`
ForeignID string `json:"foreign_id"`
SessionKey string `json:"session_key"`
Modified Time `json:"modified"`
}
// GetMetadataSessionKeys gets the Metadata Session Keys
func (c *Client) GetMetadataSessionKeys(ctx context.Context) ([]MetadataSessionKey, error) {
msg, err := c.DoCustomRequestV5(ctx, "GET", "/metadata/session-keys.json", nil, nil)
if err != nil {
return nil, err
}
var metadataSessionKeys []MetadataSessionKey
err = json.Unmarshal(msg.Body, &metadataSessionKeys)
if err != nil {
return nil, err
}
return metadataSessionKeys, nil
}
// TODO add Create and Update
// DeleteSessionKey Deletes a Passbolt SessionKey
func (c *Client) DeleteSessionKey(ctx context.Context, sessionKeyID string) error {
err := checkUUIDFormat(sessionKeyID)
if err != nil {
return fmt.Errorf("Checking ID format: %w", err)
}
_, err = c.DoCustomRequestV5(ctx, "DELETE", "/metadata/session-keys/"+sessionKeyID+".json", nil, nil)
if err != nil {
return err
}
return nil
}

View file

@ -9,7 +9,7 @@ type PassboltAPIVersionType string
const (
PassboltAPIVersionTypeV4 PassboltAPIVersionType = "v4"
PassboltAPIVersionTypeV5 = "v5"
PassboltAPIVersionTypeV5 PassboltAPIVersionType = "v5"
)
func (s PassboltAPIVersionType) IsValid() bool {
@ -59,7 +59,7 @@ func getV4DefaultMetadataTypeSettings() MetadataTypeSettings {
// GetMetadataTypeSettings gets the Servers Settings about which Types to use
func (c *Client) GetMetadataTypeSettings(ctx context.Context) (*MetadataTypeSettings, error) {
msg, err := c.DoCustomRequest(ctx, "GET", "/metadata/types/settings.json", "v3", nil, nil)
msg, err := c.DoCustomRequestV5(ctx, "GET", "/metadata/types/settings.json", nil, nil)
if err != nil {
return nil, err
}

86
api/metadatakey.go Normal file
View file

@ -0,0 +1,86 @@
package api
import (
"context"
"encoding/json"
)
type MetadataKeyType string
const (
MetadataKeyTypeUserKey MetadataKeyType = "user_key"
MetadataKeyTypeSharedKey MetadataKeyType = "shared_key"
)
func (s MetadataKeyType) IsValid() bool {
switch s {
case MetadataKeyTypeUserKey, MetadataKeyTypeSharedKey:
return true
}
return false
}
// MetadataKey is a MetadataKey
type MetadataKey struct {
ID string `json:"id,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
ArmoredKey string `json:"armored_key,omitempty"`
Created Time `json:"created,omitempty"`
Modified Time `json:"modified,omitempty"`
// These are always null? Used for Key Rotation?
//"expired": null,
//"deleted": null,
CreatedBy *string `json:"created_by,omitempty"`
ModifiedBy *string `json:"modified_by,omitempty"`
MetadataPrivateKeys []MetadataPrivateKey `json:"metadata_private_keys,omitempty"`
}
// MetadataPrivateKey is a MetadataPrivateKey
type MetadataPrivateKey struct {
ID string `json:"id,omitempty"`
MetadataKeyID string `json:"metadata_key_id,omitempty"`
UserID *string `json:"user_id,omitempty"` // TODO, is this nullable. The Docs says yes and no
Data string `json:"data,omitempty"`
Created Time `json:"created,omitempty"`
Modified Time `json:"modified,omitempty"`
CreatedBy *string `json:"created_by,omitempty"`
ModifiedBy *string `json:"modified_by,omitempty"`
}
// MetadataPrivateKeyData is a MetadataPrivateKeyData
type MetadataPrivateKeyData struct {
// ObjectType Must always be PASSBOLT_METADATA_PRIVATE_KEY
ObjectType string `json:"object_type,omitempty"`
// Domain Must be the Passbolt Server URL
Domain string `json:"domain,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
ArmoredKey string `json:"armored_key,omitempty"`
// Passphrase must be Empty for Server Keys
Passphrase string `json:"passphrase,omitempty"`
}
// GetMetadataKeysOptions are all available query parameters
type GetMetadataKeysOptions struct {
FilterDeleted bool `url:"filter[deleted],omitempty"`
FilterExpired bool `url:"filter[expired],omitempty"`
ContainMetadataPrivateKeys bool `url:"contain[metadata_private_keys],omitempty"`
}
// GetMetadataKeys gets all Passbolt GetMetadataKeys
func (c *Client) GetMetadataKeys(ctx context.Context, opts *GetMetadataKeysOptions) ([]MetadataKey, error) {
msg, err := c.DoCustomRequestV5(ctx, "GET", "/metadata/keys.json", nil, opts)
if err != nil {
return nil, err
}
var metadataKeys []MetadataKey
err = json.Unmarshal(msg.Body, &metadataKeys)
if err != nil {
return nil, err
}
return metadataKeys, nil
}

View file

@ -9,6 +9,7 @@ import (
// Resource is a Resource.
// Warning: Since Passbolt v3 some fields here may not be populated as they may be in the Secret depending on the ResourceType,
// for now the only Field like that is the Description.
// With Passbolt v5 it is now Possible that all Unencrypted User Supplied Fields are empty, and need to be decrypted from the Metadata Message
type Resource struct {
ID string `json:"id,omitempty"`
Created *Time `json:"created,omitempty"`
@ -27,6 +28,11 @@ type Resource struct {
FolderParentID string `json:"folder_parent_id,omitempty"`
ResourceTypeID string `json:"resource_type_id,omitempty"`
ResourceType ResourceType `json:"resource_type,omitempty"`
MetadataKeyID string `json:"metadata_key_id,omitempty"`
MetadataKeyType MetadataKeyType `json:"metadata_key_type,omitempty"`
Metadata string `json:"metadata,omitempty"`
Secrets []Secret `json:"secrets,omitempty"`
Tags []Tag `json:"tags,omitempty"`
}
@ -48,6 +54,8 @@ type GetResourcesOptions struct {
// Parent Folder id
FilterHasParent []string `url:"filter[has-parent][],omitempty"`
FilterHasTag string `url:"filter[has-tag],omitempty"`
// TODO Are undescores correct heare?
MetadataKeyType MetadataKeyType `url:"filter[metadata_key_type],omitempty"`
ContainCreator bool `url:"contain[creator],omitempty"`
ContainFavorites bool `url:"contain[favorite],omitempty"`

View file

@ -24,6 +24,9 @@ type User struct {
GPGKey *GPGKey `json:"gpgKey,omitempty"`
LastLoggedIn string `json:"last_logged_in,omitempty"`
Locale string `json:"locale,omitempty"`
// Admin only, needs contains
MissingMetadataKeyIDs []string `json:"missing_metadata_key_ids,omitempty"`
}
// Profile is a Profile
@ -42,6 +45,8 @@ type GetUsersOptions struct {
FilterHasGroup []string `url:"filter[has-group][],omitempty"`
FilterHasAccess []string `url:"filter[has-access][],omitempty"`
FilterIsAdmin bool `url:"filter[is-admin],omitempty"`
// Admin only, TODO are underscores correct?
MissingMetadataKeyIDs bool `url:"filter[missing_metadata_key_ids],omitempty"`
ContainLastLoggedIn bool `url:"contain[LastLoggedIn],omitempty"`
}
@ -82,10 +87,12 @@ func (c *Client) GetMe(ctx context.Context) (*User, error) {
// GetUser gets a Passbolt User
func (c *Client) GetUser(ctx context.Context, userID string) (*User, error) {
if userID != "me" {
err := checkUUIDFormat(userID)
if err != nil {
return nil, fmt.Errorf("Checking ID format: %w", err)
}
}
msg, err := c.DoCustomRequest(ctx, "GET", "/users/"+userID+".json", "v2", nil, nil)
if err != nil {
return nil, err
@ -101,10 +108,12 @@ func (c *Client) GetUser(ctx context.Context, userID string) (*User, error) {
// UpdateUser Updates a existing Passbolt User
func (c *Client) UpdateUser(ctx context.Context, userID string, user User) (*User, error) {
if userID != "me" {
err := checkUUIDFormat(userID)
if err != nil {
return nil, fmt.Errorf("Checking ID format: %w", err)
}
}
msg, err := c.DoCustomRequest(ctx, "PUT", "/users/"+userID+".json", "v2", user, nil)
if err != nil {
return nil, err
@ -119,11 +128,13 @@ func (c *Client) UpdateUser(ctx context.Context, userID string, user User) (*Use
// DeleteUser Deletes a Passbolt User
func (c *Client) DeleteUser(ctx context.Context, userID string) error {
if userID != "me" {
err := checkUUIDFormat(userID)
if err != nil {
return fmt.Errorf("Checking ID format: %w", err)
}
_, err = c.DoCustomRequest(ctx, "DELETE", "/users/"+userID+".json", "v2", nil, nil)
}
_, err := c.DoCustomRequest(ctx, "DELETE", "/users/"+userID+".json", "v2", nil, nil)
if err != nil {
return err
}