Skip to content

Conversation

@stas-schaller
Copy link
Collaborator

@stas-schaller stas-schaller commented Dec 3, 2025

Summary

Extends Terraform Provider custom field support to 5 field types (text, multiline, secret, url, email) across all 22 resource types, enabling users to add arbitrary custom fields to secrets stored in Keeper.

Changes

Extended Type Support

  • 5 field types: text, multiline, secret, url, email
  • 22 resource types: All standard, personal info, and PAM resources
  • Full CRUD operations: Create, Read, Update for custom fields
  • Type validation: Comprehensive tests for all field types

Implementation Details

Schema (record_fields.go):

  • schemaCustomField(): Schema definition supporting type, label, value, required, privacy_screen
  • convertFieldToMap(): Helper function for Update operations (converts SDK structs to RecordDict maps)

Resources (all 22 resource_*.go files):

  • Create functions: Process custom fields using switch statement for 5 types
  • Read functions: Extract custom fields from Record.RecordDict["custom"]
  • Update functions: Handle custom field changes via RecordDict manipulation

Provider (provider.go):

  • Added "custom": "custom" to field name mapping
  • Uses existing getFieldItemsResourceData() for custom field reads

Resources Supporting Custom Fields

Standard Records (11):

  • login, database_credentials, server_credentials, ssh_keys, encrypted_notes, driver_license, passport, birth_certificate, ssn_card, photo, file

Complex Nested Records (7):

  • bank_account, bank_card, payment_card, contact, health_insurance, membership, software_license

PAM Records (4):

  • pam_user, pam_machine, pam_database, pam_directory

Other (1):

  • address

Tests Added

Representative Tests (4 tests covering all 22 resources):

  1. TestAccResourceLogin_customFields - Covers 11 simple resources
  2. TestAccResourceBankAccount_customFields - Covers 7 complex nested resources
  3. TestAccResourcePamUser_customFields - Covers 4 PAM resources
  4. TestAccResourceAddress_customFields - Covers address resource

Type Validation Test:

  1. TestAccResourceLogin_customFieldTypes - Validates all 5 types (text, multiline, secret, url, email)

All tests verify:

  • Create with 2 custom fields
  • Update to 3 custom fields with value changes
  • Correct persistence across operations

Supported Field Types

All 5 types share identical SDK structure ([]string value):

type Text struct {
    KeeperRecordField
    Required      bool     `json:"required,omitempty"`
    PrivacyScreen bool     `json:"privacyScreen,omitempty"`
    Value         []string `json:"value,omitempty"`
}
// Multiline, Secret, Url, Email have identical structure

Example Usage

resource "secretsmanager_login" "employee_account" {
  folder_uid = var.folder_uid
  title      = "Employee Portal"
  
  login {
    value = "john.doe@company.com"
  }
  
  password {
    value = "securepassword123"
  }
  
  # Text custom field
  custom {
    type  = "text"
    label = "Department"
    value = "Engineering"
  }
  
  # Multiline custom field
  custom {
    type  = "multiline"
    label = "Notes"
    value = "Line 1\nLine 2\nLine 3"
  }
  
  # Secret custom field
  custom {
    type  = "secret"
    label = "API Key"
    value = "sk_live_abc123..."
  }
  
  # URL custom field
  custom {
    type  = "url"
    label = "Dashboard"
    value = "https://dashboard.example.com"
  }
  
  # Email custom field
  custom {
    type  = "email"
    label = "Support Email"
    value = "support@example.com"
  }
}

Testing

Run all custom field tests:

export TF_ACC=1
export KEEPER_CREDENTIAL="$(cat ~/.keeper/credential)"
go test ./secretsmanager -v -run "TestAccResource.*_customField" -timeout 20m

Test Results:

=== RUN   TestAccResourceAddress_customFields
--- PASS: TestAccResourceAddress_customFields (2.45s)
=== RUN   TestAccResourceBankAccount_customFields
--- PASS: TestAccResourceBankAccount_customFields (1.40s)
=== RUN   TestAccResourceLogin_customFields
--- PASS: TestAccResourceLogin_customFields (1.33s)
=== RUN   TestAccResourceLogin_customFieldTypes
--- PASS: TestAccResourceLogin_customFieldTypes (2.48s)
=== RUN   TestAccResourcePamUser_customFields
--- PASS: TestAccResourcePamUser_customFields (4.16s)
PASS
ok  	github.com/keeper-security/terraform-provider-secretsmanager/secretsmanager	11.293s

Technical Details

Custom Field Storage

Custom fields are stored separately from standard fields:

  • Standard fields: Record.RecordDict["fields"]
  • Custom fields: Record.RecordDict["custom"]

CRUD Operations

Create: Uses typed SDK structs (core.Text, core.Multiline, etc.)

field := &core.Text{
    KeeperRecordField: core.KeeperRecordField{Type: "text"},
    Label: "Department",
    Value: []string{"Engineering"},
}
nrc.Custom = append(nrc.Custom, field)

Read: Extracts from RecordDict via getFieldItemsResourceData()

customItems := getFieldItemsResourceData("custom", secret)
d.Set("custom", customItems)

Update: Manipulates RecordDict directly

fieldMap := convertFieldToMap(f.Type, f.Label, f.Required, f.PrivacyScreen, f.Value)
customFields = append(customFields, fieldMap)
secret.RecordDict["custom"] = customFields

Related Issues

idimov-keeper and others added 30 commits September 23, 2021 15:26
# Conflicts:
#	.gitignore
#	Makefile
#	go.sum
# Conflicts:
#	.gitignore
#	Makefile
#	go.sum
updated terraform-plugin-sdk to latest version
bumping KMS GoLang SDK version to v1.3.1
bumping secretsmanager version in examples
Changed test files to properly skip tests when TF_ACC is not set
instead of failing. This prevents CI from failing when running
unit tests without acceptance test credentials.

Files fixed:
- data_source_folder_test.go: removed nil pointer dereference
- resource_folder_test.go: changed t.Fail() to t.Skip()
- resource_pam_machine_test.go: changed t.Fatal() to t.Skip()
- resource_pam_database_test.go: changed t.Fatal() to t.Skip()
- Add resource_pam_user_test.go with 4 acceptance tests (create, update, delete, import)
- Add resource_pam_directory_test.go with 4 acceptance tests
- Enable PAM Database update test (was disabled due to SDK concerns)
- Add examples for PAM User resources and data sources
- Fix test data formats (checkbox values, database_type lowercase, distinguished_name labels)
- All 16 PAM acceptance tests now pass (Database, Directory, Machine, User)

Note: Update tests only test fields that work with current SDK (v1.6.4).
Fields using ApplyFieldChange() have known SDK limitation where RecordDict changes
don't sync to RawJson. Workaround: tests focus on fields using SetStandardFieldValue().
Updated version constraints in PAM resource and data source examples:
- examples/data-sources/pam_{database,machine,user}.tf
- examples/resources/pam_{database,machine,user}.tf

All PAM examples now consistently require provider version >= 1.1.8
which includes the PAM record type support added in KSM-527.
Ensure go mod tidy runs with -compat=1.24.8 to maintain compatibility
with the Go version specified in go.mod during releases, regardless of
the Go version installed on the release machine.
Implement custom field create, read, and update operations for login resources,
allowing users to add arbitrary custom fields to their secrets. This addresses
GitHub issue #16 and Jira ticket KSM-388.

Features:
- Add custom schema field to resource_login accepting list of custom fields
- Support text-type custom fields with label, value, required, and privacy_screen
- Process custom fields during resource Create operation
- Read custom fields during resource Read operation
- Update custom fields during resource Update operation
- Custom fields stored in Record.Custom array via Go SDK

Tests:
- TestAccResourceLogin_customFields: Create with 2 custom fields
- TestAccResourceLogin_customFields: Update to 3 custom fields with value changes
- Validates custom field count, labels, and values persist correctly

Schema:
- schemaCustomField(): Writable custom field schema (Optional vs Computed)
- Fields: type (required), label, value, required, privacy_screen

Helper Functions:
- getFieldItemsResourceData(): Read custom fields from Record into Terraform state
- Custom fields processed same as standard fields using NewFieldFromSchema
- ApplyFieldChange() already supports "custom" section

References: GitHub issue #16, Jira KSM-388
@stas-schaller stas-schaller force-pushed the KSM-388-custom-fields-write branch 2 times, most recently from 98ee6a5 to 2293061 Compare December 4, 2025 20:51
Add custom field write support to all resource types, enabling users to add
text-type custom fields to any Keeper record via Terraform.

Changes per resource (21 resources extended):
- Schema: Added 'custom' field using schemaCustomField()
- Create: Process custom fields from Terraform config to Record.Custom
- Read: Read custom fields from Record.Custom to Terraform state
- Update: Handle custom field changes via ApplyFieldChange()

All resources now support the same custom field pattern as resource_login
(implemented in commit 042c8a5).

Extended resources:
- address, bank_account, bank_card, birth_certificate, contact
- database_credentials, driver_license, encrypted_notes, file
- health_insurance, membership, pam_database, pam_directory
- pam_machine, pam_user, passport, photo, server_credentials
- software_license, ssh_keys, ssn_card

References: GitHub issue #16, Jira KSM-388
…d email types

Previously, custom fields only supported "text" type. This commit extends
support to include multiline, secret, url, and email types - all of which
share the same structure ([]string value) in the Go SDK.

Changes:
- Updated Create functions across all 22 resources to handle 5 field types
- Updated Update functions to properly sync all 5 types to vault
- Added convertFieldToMap helper to record_fields.go for Update operations
- Added TestAccResourceLogin_customFieldTypes to validate all types
- All existing custom field tests continue to pass

All 5 types work correctly for Create, Read, Update operations.
@stas-schaller stas-schaller force-pushed the KSM-388-custom-fields-write branch from 2293061 to 8b42042 Compare December 4, 2025 20:55
…modules-dd7da38a6b

Bump golang.org/x/crypto from 0.42.0 to 0.45.0 in the go_modules group across 1 directory
@stas-schaller stas-schaller marked this pull request as draft December 5, 2025 21:14
- Make custom field labels required
- Add validation to reject duplicate labels in Create/Update
- Add warning for duplicate labels in Read/Import
- Add comprehensive test coverage for validation logic
- Applied across all 22 resource types

Validation enforces unique labels at plan time with clear error messages.
Import operations warn users about vault records with duplicates.
Tests verify Create and Update rejection of duplicate labels.
…er_group, provider_region, alternative_ips fields
Fix gofmt indentation issues in pamDirectory resource and data source files.
@stas-schaller stas-schaller marked this pull request as ready for review December 9, 2025 16:59
@stas-schaller
Copy link
Collaborator Author

PR closed due to force-push on release-v1.1.8. Recreated as PR #68 with updated base.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants