Skip to content

Commit

Permalink
KSM-525 Allow resources to work with subfolders (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
idimov-keeper authored Jun 26, 2024
1 parent 1f699f1 commit c865e23
Show file tree
Hide file tree
Showing 37 changed files with 269 additions and 73 deletions.
2 changes: 1 addition & 1 deletion docs/resources/address.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this resource to access secrets of type `address` stored in Keeper Vault

- **address** (Block List, Max: 1) Address field data. (see [below for nested schema](#nestedblock--address))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **notes** (String) The secret notes.
- **title** (String) The secret title.
- **uid** (String) The UID of the new secret (using RFC4648 URL and Filename Safe Alphabet).
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/bank_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Use this resource to access secrets of type `bankAccount` stored in Keeper Vault
- **bank_account** (Block List, Max: 1) Bank account field data. (see [below for nested schema](#nestedblock--bank_account))
- **card_ref** (Block List, Max: 1) CardRef field data. (see [below for nested schema](#nestedblock--card_ref))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **login** (Block List, Max: 1) Login field data. (see [below for nested schema](#nestedblock--login))
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/bank_card.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Use this resource to access secrets of type `bankCard` stored in Keeper Vault
- **address_ref** (Block List, Max: 1) AddressRef field data. (see [below for nested schema](#nestedblock--address_ref))
- **cardholder_name** (Block List, Max: 1) Text field data. (see [below for nested schema](#nestedblock--cardholder_name))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **notes** (String) The secret notes.
- **payment_card** (Block List, Max: 1) Payment card field data. (see [below for nested schema](#nestedblock--payment_card))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/birth_certificate.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this resource to access secrets of type `birthCertificate` stored in Keeper

- **birth_date** (Block List, Max: 1) Birth date field data. (see [below for nested schema](#nestedblock--birth_date))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/contact.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Use this resource to access secrets of type `contact` stored in Keeper Vault
- **company** (Block List, Max: 1) Text field data. (see [below for nested schema](#nestedblock--company))
- **email** (Block List, Max: 1) Email field data. (see [below for nested schema](#nestedblock--email))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/database_credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this resource to access secrets of type `databaseCredentials` stored in Keep

- **db_type** (Block List, Max: 1) Text field data. (see [below for nested schema](#nestedblock--db_type))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **host** (Block List, Max: 1) Host field data. (see [below for nested schema](#nestedblock--host))
- **id** (String) The ID of this resource.
- **login** (Block List, Max: 1) Login field data. (see [below for nested schema](#nestedblock--login))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/driver_license.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Use this resource to access secrets of type `driverLicense` stored in Keeper Vau
- **driver_license_number** (Block List, Max: 1) Account number field data. (see [below for nested schema](#nestedblock--driver_license_number))
- **expiration_date** (Block List, Max: 1) Expiration date field data. (see [below for nested schema](#nestedblock--expiration_date))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/encrypted_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this resource to access secrets of type `encryptedNotes` stored in Keeper Va

- **date** (Block List, Max: 1) Date field data. (see [below for nested schema](#nestedblock--date))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **note** (Block List, Max: 1) Secure note field data. (see [below for nested schema](#nestedblock--note))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use this resource to access secrets of type `file` stored in Keeper Vault
### Optional

- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **notes** (String) The secret notes.
- **title** (String) The secret title.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/health_insurance.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this resource to access secrets of type `healthInsurance` stored in Keeper V

- **account_number** (Block List, Max: 1) Account number field data. (see [below for nested schema](#nestedblock--account_number))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **login** (Block List, Max: 1) Login field data. (see [below for nested schema](#nestedblock--login))
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/login.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use this resource to access secrets of type `login` stored in Keeper Vault
### Optional

- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **login** (Block List, Max: 1) Login field data. (see [below for nested schema](#nestedblock--login))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/membership.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Use this resource to access secrets of type `membership` stored in Keeper Vault

- **account_number** (Block List, Max: 1) Account number field data. (see [below for nested schema](#nestedblock--account_number))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/passport.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Use this resource to access secrets of type `passport` stored in Keeper Vault
- **date_issued** (Block List, Max: 1) Date field data. (see [below for nested schema](#nestedblock--date_issued))
- **expiration_date** (Block List, Max: 1) Expiration date field data. (see [below for nested schema](#nestedblock--expiration_date))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/photo.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use this resource to access secrets of type `photo` stored in Keeper Vault
### Optional

- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **notes** (String) The secret notes.
- **title** (String) The secret title.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/server_credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use this resource to access secrets of type `serverCredentials` stored in Keeper
### Optional

- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **host** (Block List, Max: 1) Host field data. (see [below for nested schema](#nestedblock--host))
- **id** (String) The ID of this resource.
- **login** (Block List, Max: 1) Login field data. (see [below for nested schema](#nestedblock--login))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/software_license.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Use this resource to access secrets of type `softwareLicense` stored in Keeper V
- **activation_date** (Block List, Max: 1) Date field data. (see [below for nested schema](#nestedblock--activation_date))
- **expiration_date** (Block List, Max: 1) Expiration date field data. (see [below for nested schema](#nestedblock--expiration_date))
- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **license_number** (Block List, Max: 1) License number field data. (see [below for nested schema](#nestedblock--license_number))
- **notes** (String) The secret notes.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/ssh_keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use this resource to access secrets of type `sshKeys` stored in Keeper Vault
### Optional

- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **host** (Block List, Max: 1) Host field data. (see [below for nested schema](#nestedblock--host))
- **id** (String) The ID of this resource.
- **key_pair** (Block List, Max: 1) Key pair field data. (see [below for nested schema](#nestedblock--key_pair))
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/ssn_card.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use this resource to access secrets of type `ssnCard` stored in Keeper Vault
### Optional

- **file_ref** (Block List, Max: 1) FileRef field data. (see [below for nested schema](#nestedblock--file_ref))
- **folder_uid** (String) The folder UID where the secret is stored. The shared folder must be non empty.
- **folder_uid** (String) The folder UID where the secret is stored. The parent shared folder must be non empty.
- **id** (String) The ID of this resource.
- **identity_number** (Block List, Max: 1) Account number field data. (see [below for nested schema](#nestedblock--identity_number))
- **name** (Block List, Max: 1) Name field data. (see [below for nested schema](#nestedblock--name))
Expand Down
90 changes: 89 additions & 1 deletion secretsmanager/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,11 @@ func createRecord(recordUid string, folderUid string, record *core.RecordCreate,
}
}()

ruid, err := client.CreateSecretWithRecordData(recordUid, folderUid, record)
co, err := buildCreateOptions(folderUid, client, nil)
if err != nil {
return "", err
}
ruid, err := client.CreateSecretWithRecordDataUidAndOptions(recordUid, co, record, nil)
return ruid, err
}

Expand Down Expand Up @@ -898,6 +902,90 @@ func getTemplateFolder(folderUid string, client core.SecretsManager) (fuid strin
return fuid, e
}

// getSharedFolder tries to find closest parent shared folder
func getSharedFolder(folderUid string, client core.SecretsManager, folders []*core.KeeperFolder) (fuid string, e error) {
defer func() {
if r := recover(); r != nil {
fuid = ""
switch x := r.(type) {
case string:
e = errors.New(x)
case error:
e = x
default:
e = fmt.Errorf("error in provider - getSharedFolder: %v", r)
}
}
}()

folderUid = strings.TrimSpace(folderUid)
if len(folders) == 0 {
if folders, e = client.GetFolders(); e != nil {
return "", e
}
}

fldr := struct {
ParentUid string
FolderUid string
}{
ParentUid: "",
FolderUid: "",
}
// initial lookup
for _, f := range folders {
if f.FolderUid == folderUid {
fldr.ParentUid = f.ParentUid
fldr.FolderUid = f.FolderUid
break
}
}
if fldr.FolderUid == "" {
return "", fmt.Errorf("folder not found: %v", folderUid)
} else if fldr.ParentUid == "" {
return fldr.FolderUid, nil
}
//main lookup
for {
tmpf := fldr.FolderUid
for _, f := range folders {
if f.FolderUid == fldr.ParentUid {
fldr.ParentUid = f.ParentUid
fldr.FolderUid = f.FolderUid
break
}
}
if fldr.ParentUid == "" || tmpf == fldr.FolderUid {
break
}
}
if fldr.ParentUid == "" {
return fldr.FolderUid, nil
} else {
return "", fmt.Errorf("unable to find parent folder for: %v, lookup stopped at: %v", folderUid, fldr.ParentUid)
}
}

// buildCreateOptions finds parent shared folder and returns CreateOptions
func buildCreateOptions(folderUid string, client core.SecretsManager, folders []*core.KeeperFolder) (co *core.CreateOptions, e error) {
if len(folders) == 0 {
if folders, e = client.GetFolders(); e != nil {
return nil, e
}
}

fuid, err := getSharedFolder(folderUid, client, folders)
if err != nil {
return nil, err
}

copt := core.CreateOptions{FolderUid: fuid, SubFolderUid: folderUid}
if fuid == folderUid {
copt.SubFolderUid = ""
}
return &copt, nil
}

// getStringListData splits a string into list using the separator and skipping empty parts
func GetStringListData(data string, separator string) []interface{} {
if data == "" {
Expand Down
12 changes: 9 additions & 3 deletions secretsmanager/resource_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func resourceAddress() *schema.Resource {
Computed: true,
Optional: true,
AtLeastOneOf: []string{"folder_uid", "uid"},
Description: "The folder UID where the secret is stored. The shared folder must be non empty.",
Description: "The folder UID where the secret is stored. The parent shared folder must be non empty.",
},
"uid": {
Type: schema.TypeString,
Expand Down Expand Up @@ -165,9 +165,15 @@ func resourceAddressRead(ctx context.Context, d *schema.ResourceData, m interfac
return diag.FromErr(err)
}
}
if err = d.Set("folder_uid", secret.FolderUid()); err != nil {
return diag.FromErr(err)
fuid := secret.InnerFolderUid() // in subfolder
if fuid == "" { // directly in shared folder
fuid = secret.FolderUid()
}
if fuid != "" {
if err = d.Set("folder_uid", fuid); err != nil {
return diag.FromErr(err)
}
} // else - directly shared to the KSM App (not through shared folder)
if err = d.Set("type", recordType); err != nil {
return diag.FromErr(err)
}
Expand Down
12 changes: 9 additions & 3 deletions secretsmanager/resource_bank_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func resourceBankAccount() *schema.Resource {
Computed: true,
Optional: true,
AtLeastOneOf: []string{"folder_uid", "uid"},
Description: "The folder UID where the secret is stored. The shared folder must be non empty.",
Description: "The folder UID where the secret is stored. The parent shared folder must be non empty.",
},
"uid": {
Type: schema.TypeString,
Expand Down Expand Up @@ -238,9 +238,15 @@ func resourceBankAccountRead(ctx context.Context, d *schema.ResourceData, m inte
return diag.FromErr(err)
}
}
if err = d.Set("folder_uid", secret.FolderUid()); err != nil {
return diag.FromErr(err)
fuid := secret.InnerFolderUid() // in subfolder
if fuid == "" { // directly in shared folder
fuid = secret.FolderUid()
}
if fuid != "" {
if err = d.Set("folder_uid", fuid); err != nil {
return diag.FromErr(err)
}
} // else - directly shared to the KSM App (not through shared folder)
if err = d.Set("type", recordType); err != nil {
return diag.FromErr(err)
}
Expand Down
12 changes: 9 additions & 3 deletions secretsmanager/resource_bank_card.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func resourceBankCard() *schema.Resource {
Computed: true,
Optional: true,
AtLeastOneOf: []string{"folder_uid", "uid"},
Description: "The folder UID where the secret is stored. The shared folder must be non empty.",
Description: "The folder UID where the secret is stored. The parent shared folder must be non empty.",
},
"uid": {
Type: schema.TypeString,
Expand Down Expand Up @@ -198,9 +198,15 @@ func resourceBankCardRead(ctx context.Context, d *schema.ResourceData, m interfa
return diag.FromErr(err)
}
}
if err = d.Set("folder_uid", secret.FolderUid()); err != nil {
return diag.FromErr(err)
fuid := secret.InnerFolderUid() // in subfolder
if fuid == "" { // directly in shared folder
fuid = secret.FolderUid()
}
if fuid != "" {
if err = d.Set("folder_uid", fuid); err != nil {
return diag.FromErr(err)
}
} // else - directly shared to the KSM App (not through shared folder)
if err = d.Set("type", recordType); err != nil {
return diag.FromErr(err)
}
Expand Down
Loading

0 comments on commit c865e23

Please sign in to comment.