Skip to content

Commit 955598e

Browse files
committed
feat(migrate): re-use existing migration target pam provider if it exists
1 parent 2d4cfbd commit 955598e

File tree

1 file changed

+133
-92
lines changed

1 file changed

+133
-92
lines changed

cmd/migrate.go

Lines changed: 133 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package cmd
1717
import (
1818
"context"
1919
"encoding/json"
20+
"errors"
2021
"fmt"
2122

2223
// "github.com/Keyfactor/keyfactor-go-client-sdk/v24/api/keyfactor/v2"
@@ -72,25 +73,15 @@ var migratePamCmd = &cobra.Command{
7273
// TODO: assign error and check
7374
legacyClient, _ := initClient(false)
7475

75-
log.Info().Msg("looking up usage of <<from>> PAM Provider")
76+
found, fromPamProvider, processedError := getExistingPamProvider(sdkClient, migrateFrom)
7677

77-
log.Debug().Msg("call: PAMProviderGetPamProviders()")
78-
listPamProvidersInUse, httpResponse, rErr := sdkClient.PAMProviderApi.PAMProviderGetPamProviders(context.Background()).
79-
XKeyfactorRequestedWith(XKeyfactorRequestedWith).XKeyfactorApiVersion(XKeyfactorApiVersion).
80-
PqQueryString(fmt.Sprintf("name -eq \"%s\"", migrateFrom)).
81-
Execute()
82-
log.Debug().Msg("returned: PAMProviderGetPamProviders()")
83-
84-
if rErr != nil {
85-
log.Error().Err(rErr).Send()
86-
return returnHttpErr(httpResponse, rErr)
78+
if processedError != nil {
79+
return processedError
8780
}
8881

89-
jobject, _ := json.MarshalIndent(listPamProvidersInUse, "", " ")
90-
fmt.Println(string(jobject))
91-
92-
// TODO: ensure only 1 returned PAM Provider definition
93-
fromPamProvider := listPamProvidersInUse[0]
82+
if found == false {
83+
return errors.New("Original PAM Provider to migrate from was not found by Name")
84+
}
9485

9586
// get PAM Type definition for PAM Provider migrating <<FROM>>
9687
log.Debug().Msg("call: PAMProviderGetPamProviders()")
@@ -151,14 +142,14 @@ var migratePamCmd = &cobra.Command{
151142
}
152143
}
153144

154-
jobject, _ = json.MarshalIndent(inUsePamParamValues, "", " ")
145+
jobject, _ := json.MarshalIndent(inUsePamParamValues, "", " ")
155146
fmt.Println(string(jobject))
156147

157148
// step through list of every defined param value
158149
// record unique GUIDs of every param value on InstanceLevel : true
159150
// InstanceLevel : true is for per-secret fields
160151
// InstanceLevel : false is provider level secrets - these are also recorded for migration
161-
for _, pamParam := range listPamProvidersInUse[0].ProviderTypeParamValues {
152+
for _, pamParam := range fromPamProvider.ProviderTypeParamValues {
162153
// jobject, _ = json.MarshalIndent(pamParam, "", " ")
163154
// fmt.Println(string(jobject))
164155
fieldName := *pamParam.ProviderTypeParam.Name
@@ -182,87 +173,24 @@ var migratePamCmd = &cobra.Command{
182173
// mark GUID ID for pam type
183174
// mark integer IDs for each Parameter type
184175

185-
// TODO: check that migration target PAM Provider was not already created
176+
var migrationTargetPamProvider keyfactor.CSSCMSDataModelModelsProvider
186177

187-
fmt.Println("creating new Provider of migration target PAM Type")
188-
var migrationPamProvider keyfactor.CSSCMSDataModelModelsProvider
189-
migrationPamProvider.Name = fromPamProvider.Name + appendName
190-
migrationPamProvider.ProviderType = keyfactor.CSSCMSDataModelModelsProviderType{
191-
Id: toPamType.Id,
192-
}
193-
var onevalue int32 = 1
194-
migrationPamProvider.Area = &onevalue
195-
migrationPamProvider.SecuredAreaId = nil
178+
// check if target PAM Provider already exists
179+
found, migrationTargetPamProvider, processedError = getExistingPamProvider(sdkClient, fromPamProvider.Name+appendName)
196180

197-
// need to init AdditionalProperties map when setting value
198-
migrationPamProvider.AdditionalProperties = map[string]interface{}{
199-
"Remote": false, // this property is not on the model for some reason
181+
if processedError != nil {
182+
return processedError
200183
}
201184

202-
fmt.Println("getting migration target PAM Type parameter definitions, InstanceLevel : false")
203-
// TODO: check typing, have to access "Parameters" instead of ProviderTypeParams
204-
for _, pamParamType := range fromPamType.AdditionalProperties["Parameters"].([]interface{}) {
205-
if !pamParamType.(map[string]interface{})["InstanceLevel"].(bool) {
206-
// found a provider level parameter
207-
// need to find the value to map over
208-
// then create an object with that value and TypeParam settings
209-
paramName := pamParamType.(map[string]interface{})["Name"].(string)
210-
paramValue := selectProviderParamValue(paramName, fromPamProvider.ProviderTypeParamValues)
211-
paramTypeId := selectProviderTypeParamId(paramName, toPamType.AdditionalProperties["Parameters"].([]interface{}))
212-
falsevalue := false
213-
providerLevelParameter := keyfactor.CSSCMSDataModelModelsPamProviderTypeParamValue{
214-
Value: &paramValue,
215-
ProviderTypeParam: &keyfactor.CSSCMSDataModelModelsProviderTypeParam{
216-
Id: &paramTypeId,
217-
Name: &paramName,
218-
InstanceLevel: &falsevalue,
219-
},
220-
}
221-
222-
// append filled out provider type parameter object, which contains the Provider-level parameter values
223-
// migrationPamProvider.ProviderTypeParamValues = append(migrationPamProvider.ProviderTypeParamValues, providerLevelParameter)
185+
// create PAM Provider if it does not exist already
186+
if found == false {
187+
migrationTargetPamProvider, processedError = createMigrationTargetPamProvider(sdkClient, fromPamProvider, fromPamType, toPamType, appendName)
224188

225-
// TODO: need to explicit filter for CyberArk expected params, i.e. not map over Safe
226-
// this needs to be done programatically for other provider types
227-
if paramName == "AppId" {
228-
migrationPamProvider.ProviderTypeParamValues = append(migrationPamProvider.ProviderTypeParamValues, providerLevelParameter)
229-
}
189+
if processedError != nil {
190+
return processedError
230191
}
231192
}
232193

233-
msg := "Created new PAM Provider definition to be created."
234-
fmt.Println(msg)
235-
log.Info().Msg(msg)
236-
jobject, _ = json.MarshalIndent(migrationPamProvider, "", " ")
237-
fmt.Println(string(jobject))
238-
fmt.Println("^^^ PAM Provider to be created ^^^")
239-
240-
// POST new PAM Provider
241-
// create new PAM Instance of designated <<TO>> type
242-
// set area = 1 or previous value
243-
// name = old name plus append parameter
244-
// providertype.id = Type GUID
245-
// for all provider level values:
246-
// set value to migrating value
247-
// null for instanceid, instanceguid
248-
// providertypeparam should be set to all matching values from GET TYPES
249-
// ignoring datatype
250-
251-
createdPamProvider, httpResponse, rErr := sdkClient.PAMProviderApi.PAMProviderCreatePamProvider(context.Background()).
252-
Provider(migrationPamProvider).
253-
XKeyfactorRequestedWith(XKeyfactorRequestedWith).XKeyfactorApiVersion(XKeyfactorApiVersion).
254-
Execute()
255-
256-
if rErr != nil {
257-
log.Error().Err(rErr).Send()
258-
return returnHttpErr(httpResponse, rErr)
259-
}
260-
261-
fmt.Println("vvv CREATED MIGRATION PAM PROVIDER vvv")
262-
jobject, _ = json.MarshalIndent(createdPamProvider, "", " ")
263-
fmt.Println(string(jobject))
264-
fmt.Println("^^^ CREATED MIGRATION PAM PROVIDER ^^^")
265-
266194
// foreach store GUID pass in as a parameter-----
267195
// GET Store by GUID (instance GUID matches Store Id GUID)
268196
// output some store info to confirm
@@ -300,7 +228,7 @@ var migratePamCmd = &cobra.Command{
300228
// check if Pam Secret is using our migrating provider
301229
if *fromPamProvider.Id == int32(propSecret["ProviderId"].(float64)) {
302230
// Pam Secret that Needs to be migrated
303-
formattedSecret["Value"] = buildMigratedPamSecret(propSecret, fromProviderLevelParamValues, *createdPamProvider.Id)
231+
formattedSecret["Value"] = buildMigratedPamSecret(propSecret, fromProviderLevelParamValues, *migrationTargetPamProvider.Id)
304232
} else {
305233
// reformat to required POST format for properties
306234
formattedSecret["Value"] = reformatPamSecretForPost(propSecret)
@@ -354,6 +282,119 @@ var migratePamCmd = &cobra.Command{
354282
},
355283
}
356284

285+
func getExistingPamProvider(sdkClient *keyfactor.APIClient, name string) (bool, keyfactor.CSSCMSDataModelModelsProvider, error) {
286+
var pamProvider keyfactor.CSSCMSDataModelModelsProvider
287+
288+
logMsg := fmt.Sprintf("Looking up usage of PAM Provider with name %s", name)
289+
log.Debug().Msg(logMsg)
290+
fmt.Println(logMsg)
291+
292+
foundProvider, httpResponse, err := sdkClient.PAMProviderApi.PAMProviderGetPamProviders(context.Background()).
293+
XKeyfactorRequestedWith(XKeyfactorRequestedWith).XKeyfactorApiVersion(XKeyfactorApiVersion).
294+
PqQueryString(fmt.Sprintf("name -eq \"%s\"", name)).
295+
Execute()
296+
297+
logMsg = fmt.Sprintf("Reading response for PAM Provider with name %s", name)
298+
log.Debug().Msg(logMsg)
299+
fmt.Println(logMsg)
300+
301+
if err != nil {
302+
log.Error().Err(err).Send()
303+
return false, pamProvider, returnHttpErr(httpResponse, err)
304+
}
305+
306+
if len(foundProvider) != 1 {
307+
logMsg = "More than one PAM Provider returned for the same name. This is not supported behavior."
308+
log.Error().Msg(logMsg)
309+
return false, pamProvider, errors.New(logMsg)
310+
}
311+
312+
return true, foundProvider[0], nil
313+
}
314+
315+
func createMigrationTargetPamProvider(sdkClient *keyfactor.APIClient, fromPamProvider keyfactor.CSSCMSDataModelModelsProvider, fromPamType keyfactor.CSSCMSDataModelModelsProviderType, toPamType keyfactor.CSSCMSDataModelModelsProviderType, appendName string) (keyfactor.CSSCMSDataModelModelsProvider, error) {
316+
fmt.Println("creating new Provider of migration target PAM Type")
317+
var migrationPamProvider keyfactor.CSSCMSDataModelModelsProvider
318+
migrationPamProvider.Name = fromPamProvider.Name + appendName
319+
migrationPamProvider.ProviderType = keyfactor.CSSCMSDataModelModelsProviderType{
320+
Id: toPamType.Id,
321+
}
322+
var onevalue int32 = 1
323+
migrationPamProvider.Area = &onevalue
324+
migrationPamProvider.SecuredAreaId = nil
325+
326+
// need to init AdditionalProperties map when setting value
327+
migrationPamProvider.AdditionalProperties = map[string]interface{}{
328+
"Remote": false, // this property is not on the model for some reason
329+
}
330+
331+
fmt.Println("getting migration target PAM Type parameter definitions, InstanceLevel : false")
332+
// TODO: check typing, have to access "Parameters" instead of ProviderTypeParams
333+
for _, pamParamType := range fromPamType.AdditionalProperties["Parameters"].([]interface{}) {
334+
if !pamParamType.(map[string]interface{})["InstanceLevel"].(bool) {
335+
// found a provider level parameter
336+
// need to find the value to map over
337+
// then create an object with that value and TypeParam settings
338+
paramName := pamParamType.(map[string]interface{})["Name"].(string)
339+
paramValue := selectProviderParamValue(paramName, fromPamProvider.ProviderTypeParamValues)
340+
paramTypeId := selectProviderTypeParamId(paramName, toPamType.AdditionalProperties["Parameters"].([]interface{}))
341+
falsevalue := false
342+
providerLevelParameter := keyfactor.CSSCMSDataModelModelsPamProviderTypeParamValue{
343+
Value: &paramValue,
344+
ProviderTypeParam: &keyfactor.CSSCMSDataModelModelsProviderTypeParam{
345+
Id: &paramTypeId,
346+
Name: &paramName,
347+
InstanceLevel: &falsevalue,
348+
},
349+
}
350+
351+
// append filled out provider type parameter object, which contains the Provider-level parameter values
352+
// migrationPamProvider.ProviderTypeParamValues = append(migrationPamProvider.ProviderTypeParamValues, providerLevelParameter)
353+
354+
// TODO: need to explicit filter for CyberArk expected params, i.e. not map over Safe
355+
// this needs to be done programatically for other provider types
356+
if paramName == "AppId" {
357+
migrationPamProvider.ProviderTypeParamValues = append(migrationPamProvider.ProviderTypeParamValues, providerLevelParameter)
358+
}
359+
}
360+
}
361+
362+
msg := "Created new PAM Provider definition to be created."
363+
fmt.Println(msg)
364+
log.Info().Msg(msg)
365+
jobject, _ := json.MarshalIndent(migrationPamProvider, "", " ")
366+
fmt.Println(string(jobject))
367+
fmt.Println("^^^ PAM Provider to be created ^^^")
368+
369+
// POST new PAM Provider
370+
// create new PAM Instance of designated <<TO>> type
371+
// set area = 1 or previous value
372+
// name = old name plus append parameter
373+
// providertype.id = Type GUID
374+
// for all provider level values:
375+
// set value to migrating value
376+
// null for instanceid, instanceguid
377+
// providertypeparam should be set to all matching values from GET TYPES
378+
// ignoring datatype
379+
380+
createdPamProvider, httpResponse, rErr := sdkClient.PAMProviderApi.PAMProviderCreatePamProvider(context.Background()).
381+
Provider(migrationPamProvider).
382+
XKeyfactorRequestedWith(XKeyfactorRequestedWith).XKeyfactorApiVersion(XKeyfactorApiVersion).
383+
Execute()
384+
385+
if rErr != nil {
386+
log.Error().Err(rErr).Send()
387+
return *createdPamProvider, returnHttpErr(httpResponse, rErr)
388+
}
389+
390+
fmt.Println("vvv CREATED MIGRATION PAM PROVIDER vvv")
391+
jobject, _ = json.MarshalIndent(createdPamProvider, "", " ")
392+
fmt.Println(string(jobject))
393+
fmt.Println("^^^ CREATED MIGRATION PAM PROVIDER ^^^")
394+
395+
return *createdPamProvider, nil
396+
}
397+
357398
func selectProviderParamValue(name string, providerParameters []keyfactor.CSSCMSDataModelModelsPamProviderTypeParamValue) string {
358399
for _, parameter := range providerParameters {
359400
if name == *parameter.ProviderTypeParam.Name {

0 commit comments

Comments
 (0)