Skip to content

Commit

Permalink
feat: add writing managed accounts feature in terraform provider
Browse files Browse the repository at this point in the history
  • Loading branch information
btfhernandez committed Nov 5, 2024
1 parent cddb485 commit 87c0cbd
Show file tree
Hide file tree
Showing 5 changed files with 572 additions and 1 deletion.
46 changes: 46 additions & 0 deletions TestClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/BeyondTrust/go-client-library-passwordsafe/api/authentication"
"github.com/BeyondTrust/go-client-library-passwordsafe/api/entities"
logging "github.com/BeyondTrust/go-client-library-passwordsafe/api/logging"
managed_accounts "github.com/BeyondTrust/go-client-library-passwordsafe/api/managed_account"
"github.com/BeyondTrust/go-client-library-passwordsafe/api/secrets"
Expand Down Expand Up @@ -112,6 +113,51 @@ func main() {
// WARNING: Do not log secrets in production code, the following log statement logs test secrets for testing purposes:
zapLogger.Warn(fmt.Sprintf("%v", gotManagedAccount))

account := entities.AccountDetails{
AccountName: "ManagedAccountTest",
Password: "Passw0rd101!*",
DomainName: "exampleDomain",
UserPrincipalName: "[email protected]",
SAMAccountName: "samAccount",
DistinguishedName: "CN=example,CN=Users,DC=domain,DC=com",
PrivateKey: "privateKey",
Passphrase: "passphrase",
PasswordFallbackFlag: true,
LoginAccountFlag: false,
Description: "Sample account for testing",
ApiEnabled: true,
ReleaseNotificationEmail: "[email protected]",
ChangeServicesFlag: false,
RestartServicesFlag: false,
ChangeTasksFlag: true,
MaxReleaseDuration: 300000,
ISAReleaseDuration: 180,
MaxConcurrentRequests: 5,
AutoManagementFlag: false,
DSSAutoManagementFlag: false,
CheckPasswordFlag: true,
ResetPasswordOnMismatchFlag: false,
ChangePasswordAfterAnyReleaseFlag: true,
ChangeFrequencyDays: 1,
ChangeTime: "",
NextChangeDate: "2023-12-01",
UseOwnCredentials: true,
ChangeWindowsAutoLogonFlag: true,
ChangeComPlusFlag: false,
ObjectID: "uniqueObjectID",
}

// creating a managed account in system_integration_test system.
createResponse, err := manageAccountObj.ManageAccountCreateFlow("system_integration_test", account)

if err != nil {
zapLogger.Error(fmt.Sprintf(" %v", err))
return
}

// WARNING: created managed account name.
zapLogger.Warn(fmt.Sprintf("Created Managed Account: %v", createResponse.AccountName))

// signing out
_ = authenticate.SignOut()

Expand Down
51 changes: 51 additions & 0 deletions api/entities/entities.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,54 @@ type GetTokenResponse struct {
TokenType string `json:"token_type"`
Scope string `json:"scope"`
}

type ManagedSystemResponse struct {
ManagedSystemID int
SystemName string
}

type CreateManagedAccountsResponse struct {
ManagedAccountID int
ManagedSystemID int
AccountName string
}

type AccountDetails struct {
AccountName string `validate:"required,max=245"`
Password string `validate:"required_if=AutoManagementFlag false"`
DomainName string `validate:"max=50"`
UserPrincipalName string `validate:"omitempty,max=500"`
SAMAccountName string `validate:"omitempty,max=20"`
DistinguishedName string `validate:"omitempty,max=1000"`
PrivateKey string `validate:"omitempty"`
Passphrase string `validate:"omitempty,required_if=PrivateKey Encrypted"`
PasswordFallbackFlag bool `validate:"omitempty"`
LoginAccountFlag bool `validate:"omitempty"`
Description string `validate:"omitempty,max=1024"`
PasswordRuleID int `validate:"omitempty,gte=0"`
ApiEnabled bool `validate:"omitempty"`
ReleaseNotificationEmail string `validate:"omitempty,email,max=255"`
ChangeServicesFlag bool `validate:"omitempty"`
RestartServicesFlag bool `validate:"omitempty"`
ChangeTasksFlag bool `validate:"omitempty"`
ReleaseDuration int `validate:"omitempty,min=1,max=525600,ltefield=MaxReleaseDuration"`
MaxReleaseDuration int `validate:"omitempty,min=1,max=525600"`
ISAReleaseDuration int `validate:"omitempty,min=1,max=525600"`
MaxConcurrentRequests int `validate:"omitempty,min=0,max=999"`
AutoManagementFlag bool `validate:"omitempty"`
DSSAutoManagementFlag bool `validate:"omitempty"`
CheckPasswordFlag bool `validate:"omitempty"`
ChangePasswordAfterAnyReleaseFlag bool `validate:"omitempty"`
ResetPasswordOnMismatchFlag bool `validate:"omitempty"`
ChangeFrequencyType string `validate:"omitempty,oneof=first last xdays"`
ChangeFrequencyDays int `validate:"omitempty,min=1,max=999"`
ChangeTime string `validate:"omitempty,datetime=15:04"`
NextChangeDate string `validate:"omitempty,datetime=2006-01-02"`
UseOwnCredentials bool `validate:"omitempty"`
WorkgroupID *int `validate:"omitempty"`
ChangeWindowsAutoLogonFlag bool `validate:"omitempty"`
ChangeComPlusFlag bool `validate:"omitempty"`
ChangeDComFlag bool `validate:"omitempty"`
ChangeSComFlag bool `validate:"omitempty"`
ObjectID string `validate:"omitempty,max=36"`
}
144 changes: 143 additions & 1 deletion api/managed_account/managed_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/BeyondTrust/go-client-library-passwordsafe/api/entities"
"github.com/BeyondTrust/go-client-library-passwordsafe/api/logging"
"github.com/BeyondTrust/go-client-library-passwordsafe/api/utils"

backoff "github.com/cenkalti/backoff/v4"
)

Expand Down Expand Up @@ -250,3 +249,146 @@ func (managedAccounObj *ManagedAccountstObj) ManagedAccountRequestCheckIn(reques

return "", nil
}

// ManageAccountCreateFlow is responsible for creating a managed accounts in Password Safe.
func (managedAccounObj *ManagedAccountstObj) ManageAccountCreateFlow(systemNameTarget string, accountDetails entities.AccountDetails) (entities.CreateManagedAccountsResponse, error) {

var managedSystem *entities.ManagedSystemResponse
var createResponse entities.CreateManagedAccountsResponse

accountDetails, err := utils.ValidateCreateManagedAccountInput(accountDetails)

if err != nil {
return createResponse, err
}

ManagedAccountSytemUrl := managedAccounObj.authenticationObj.ApiUrl.JoinPath("ManagedSystems").String()
managedSystemGetSystemsResponse, err := managedAccounObj.ManagedSystemGetSystems(ManagedAccountSytemUrl)

if err != nil {
return createResponse, err
}

for _, v := range managedSystemGetSystemsResponse {
if v.SystemName == systemNameTarget {
managedSystem = &v
break
}
}

if managedSystem == nil {
return createResponse, fmt.Errorf("managed system %v was not found in managed system list", systemNameTarget)
}

ManagedAccountCreateManagedAccountUrl := managedAccounObj.authenticationObj.ApiUrl.JoinPath("ManagedSystems", fmt.Sprintf("%d", managedSystem.ManagedSystemID), "ManagedAccounts").String()
createResponse, err = managedAccounObj.ManagedAccountCreateManagedAccount(accountDetails, ManagedAccountCreateManagedAccountUrl)

if err != nil {
return createResponse, err
}

return createResponse, nil

}

// ManagedAccountCreateManagedAccount calls Secret Safe API Requests enpoint to create managed accounts.
func (managedAccounObj *ManagedAccountstObj) ManagedAccountCreateManagedAccount(accountDetails entities.AccountDetails, url string) (entities.CreateManagedAccountsResponse, error) {
messageLog := fmt.Sprintf("%v %v", "POST", url)
managedAccounObj.log.Debug(messageLog)

accountDetailsJson, err := json.Marshal(accountDetails)
if err != nil {
return entities.CreateManagedAccountsResponse{}, err
}

accountDetailsJsonString := string(accountDetailsJson)

managedAccounObj.log.Debug(accountDetailsJsonString)

b := bytes.NewBufferString(accountDetailsJsonString)

var body io.ReadCloser
var technicalError error
var businessError error

technicalError = backoff.Retry(func() error {
body, _, technicalError, businessError = managedAccounObj.authenticationObj.HttpClient.CallSecretSafeAPI(url, "POST", *b, "ManagedAccountCreateManagedAccount", "", "")
return technicalError
}, managedAccounObj.authenticationObj.ExponentialBackOff)

var CreateManagedAccountsResponse entities.CreateManagedAccountsResponse

if technicalError != nil {
return entities.CreateManagedAccountsResponse{}, technicalError
}

if businessError != nil {
return entities.CreateManagedAccountsResponse{}, businessError
}

defer body.Close()
bodyBytes, err := io.ReadAll(body)

if err != nil {
return entities.CreateManagedAccountsResponse{}, err
}

err = json.Unmarshal([]byte(bodyBytes), &CreateManagedAccountsResponse)

if err != nil {
managedAccounObj.log.Error(err.Error())
return entities.CreateManagedAccountsResponse{}, err
}

return CreateManagedAccountsResponse, nil

}

// ManagedAccountGetSystem is responsible for retrieving managed systems list
func (managedAccounObj *ManagedAccountstObj) ManagedSystemGetSystems(url string) ([]entities.ManagedSystemResponse, error) {
messageLog := fmt.Sprintf("%v %v", "GET", url)
managedAccounObj.log.Debug(messageLog)

var body io.ReadCloser
var technicalError error
var businessError error

technicalError = backoff.Retry(func() error {
body, _, technicalError, businessError = managedAccounObj.authenticationObj.HttpClient.CallSecretSafeAPI(url, "GET", bytes.Buffer{}, "ManagedSystemGetSystems", "", "")
if technicalError != nil {
return technicalError
}
return nil

}, managedAccounObj.authenticationObj.ExponentialBackOff)

var managedSystemObject []entities.ManagedSystemResponse

if technicalError != nil {
return managedSystemObject, technicalError
}

if businessError != nil {
return managedSystemObject, businessError
}

defer body.Close()
bodyBytes, err := io.ReadAll(body)

if err != nil {
return managedSystemObject, err
}

err = json.Unmarshal(bodyBytes, &managedSystemObject)
if err != nil {
managedAccounObj.log.Error(err.Error())
return managedSystemObject, err
}

if len(managedSystemObject) == 0 {
return managedSystemObject, fmt.Errorf("empty System Account List")
}

return managedSystemObject, nil

}
Loading

0 comments on commit 87c0cbd

Please sign in to comment.