From 53f83445715ffb6bca0dbb895752f8d8d053f233 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:04:05 -0700 Subject: [PATCH 01/24] fix(stores): `stores import` providing a `Password(/StorePassword)` does not crash CLI. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 45d61fa..98ece73 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -286,7 +286,15 @@ var storesCreateFromCSVCmd = &cobra.Command{ // parse properties var createStoreReqParameters api.CreateStoreFctArgs props := unmarshalPropertiesString(reqJson.S("Properties").String()) + storePasswd := reqJson.S("Password").String() reqJson.Delete("Properties") // todo: why is this deleting the properties from the request json? + var passwdParams *api.StorePasswordConfig + if storePasswd != "" { + reqJson.Delete("Password") + passwdParams = &api.StorePasswordConfig{ + Value: &storePasswd, + } + } mJSON := reqJson.String() conversionError := json.Unmarshal([]byte(mJSON), &createStoreReqParameters) @@ -299,6 +307,7 @@ var storesCreateFromCSVCmd = &cobra.Command{ return conversionError } + createStoreReqParameters.Password = passwdParams createStoreReqParameters.Properties = props log.Debug().Msgf("Request parameters: %v", createStoreReqParameters) From b66dedde8f4e22d3056f240e0ffbd7b4d60e9b98 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:14:29 -0700 Subject: [PATCH 02/24] chore(deps): Update all explicit imports to latest. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- go.mod | 38 +++++++++++++-------------- go.sum | 81 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/go.mod b/go.mod index 38cdf70..4a62897 100644 --- a/go.mod +++ b/go.mod @@ -1,42 +1,42 @@ module kfutil -go 1.23 +go 1.23.0 -toolchain go1.23.2 +toolchain go1.24.2 require ( github.com/AlecAivazis/survey/v2 v2.3.7 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 github.com/Jeffail/gabs v1.4.0 - github.com/Keyfactor/keyfactor-auth-client-go v1.2.0-rc.9 + github.com/Keyfactor/keyfactor-auth-client-go v1.2.0 github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 github.com/creack/pty v1.1.24 - github.com/google/go-cmp v0.6.0 + github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/hinshun/vt10x v0.0.0-20220301184237-5011da428d02 github.com/joho/godotenv v1.5.1 - github.com/rs/zerolog v1.33.0 - github.com/spf13/cobra v1.8.1 - github.com/spf13/pflag v1.0.5 + github.com/rs/zerolog v1.34.0 + github.com/spf13/cobra v1.9.1 + github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.32.0 - golang.org/x/term v0.28.0 + golang.org/x/crypto v0.37.0 + golang.org/x/term v0.31.0 gopkg.in/yaml.v3 v3.0.1 //github.com/google/go-cmp/cmp v0.5.9 ) require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.18.0 // indirect - github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -44,15 +44,15 @@ require ( github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spbsoluble/go-pkcs12 v0.3.3 // indirect go.mozilla.org/pkcs7 v0.9.0 // indirect - golang.org/x/net v0.34.0 // indirect + golang.org/x/net v0.39.0 // indirect golang.org/x/oauth2 v0.25.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 440c026..fedff68 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,25 @@ github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.0 h1:WLUIpeyv04H0RCcQHaA4TNoyrQ39Ox7V+re+iaqzTe0= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.0/go.mod h1:hd8hTTIY3VmUVPRHNH7GVCHO3SHgXkJKZHReby/bnUQ= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 h1:eXnN9kaS8TiDwXjoie3hMRLuwdUBUMW9KRgOqB3mCaw= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0/go.mod h1:XIpam8wumeZ5rVMuhdDQLMfIPDf1WO3IzrCRO3e3e3o= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.0-rc.9 h1:CaPTRbFwssCFPvFQlKE4h+0LG6mKMIjAtnniuiZp+38= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.0-rc.9/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.0 h1:uNSlyOW5Bqpi0nsOGZtOYQzN0vP/h4S4J38jtQes+OI= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.0/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 h1:ehk5crxEGVBwkC8yXsoQXcyITTDlgbxMEkANrl1dA2Q= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0/go.mod h1:11WXGG9VVKSV0EPku1IswjHbGGpzHDKqD4pe2vD7vas= github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 h1:DQgb93m3xHZZ0FxWGFS90XI8prwS5fmIGrXNxP2IfHM= @@ -29,8 +29,8 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDe github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= @@ -43,10 +43,10 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= @@ -62,8 +62,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -83,8 +83,9 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -92,21 +93,21 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= -github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= +github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spbsoluble/go-pkcs12 v0.3.3 h1:3nh7IKn16RDpmrSMtOu1JvbB0XHYq1j+IsICdU1c7J4= github.com/spbsoluble/go-pkcs12 v0.3.3/go.mod h1:MAxKIUEIl/QVcua/I1L4Otyxl9UvLCCIktce2Tjz6Nw= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= @@ -117,14 +118,14 @@ go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI= go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -144,18 +145,18 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From 3c126672e37625151c7a4d88c2f1796ce6248d1d Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:15:22 -0700 Subject: [PATCH 03/24] feat(stores): `import csv` add support for credential input via flags and/or user interactive prompt. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 63 ++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 98ece73..3b5f1c6 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -117,6 +117,9 @@ var storesCreateFromCSVCmd = &cobra.Command{ filePath, _ := cmd.Flags().GetString("file") outPath, _ := cmd.Flags().GetString("results-path") dryRun, _ := cmd.Flags().GetBool("dry-run") + serverUsername, _ := cmd.Flags().GetString("server-username") + serverPassword, _ := cmd.Flags().GetString("server-password") + storePassword, _ := cmd.Flags().GetString("store-password") //// Flag Checks //inputErr := storeTypeIdentifierFlagCheck(cmd) @@ -259,6 +262,19 @@ var storesCreateFromCSVCmd = &cobra.Command{ errorCount := 0 + if !noPrompt { + promptCreds := promptForInteractiveYesNo("Input default credentials to use for certificate stores?") + if promptCreds { + outputResult("NOTE: Credentials provided in file will take precedence over prompts.", outputFormat) + serverUsername = promptForInteractiveParameter("ServerUsername", serverUsername) + log.Debug().Str("serverUsername", serverUsername).Msg("ServerUsername") + serverPassword = promptForInteractivePassword("ServerPassword", serverPassword) + log.Debug().Str("serverPassword", hashSecretValue(serverPassword)).Msg("ServerPassword") + storePassword = promptForInteractivePassword("StorePassword", storePassword) + log.Debug().Str("storePassword", hashSecretValue(storePassword)).Msg("StorePassword") + } + } + log.Info().Msgf("Processing CSV rows from file '%s'", filePath) for idx, row := range inFile { log.Debug().Msgf("Processing row '%d'", idx) @@ -270,7 +286,6 @@ var storesCreateFromCSVCmd = &cobra.Command{ continue } reqJson := getJsonForRequest(headerRow, row) - reqJson = formatProperties(reqJson, reqPropertiesForStoreType) reqJson.Set(intID, "CertStoreType") @@ -286,13 +301,29 @@ var storesCreateFromCSVCmd = &cobra.Command{ // parse properties var createStoreReqParameters api.CreateStoreFctArgs props := unmarshalPropertiesString(reqJson.S("Properties").String()) - storePasswd := reqJson.S("Password").String() + + //check if ServerUsername is present in the properties + _, uOk := props["ServerUsername"] + if !uOk && serverUsername != "" { + props["ServerUsername"] = serverUsername + } + + _, pOk := props["ServerPassword"] + if !pOk && serverPassword != "" { + props["ServerPassword"] = serverPassword + } + + rowStorePassword := reqJson.S("Password").String() reqJson.Delete("Properties") // todo: why is this deleting the properties from the request json? var passwdParams *api.StorePasswordConfig - if storePasswd != "" { + if rowStorePassword != "" { reqJson.Delete("Password") passwdParams = &api.StorePasswordConfig{ - Value: &storePasswd, + Value: &rowStorePassword, + } + } else { + passwdParams = &api.StorePasswordConfig{ + Value: &storePassword, } } mJSON := reqJson.String() @@ -311,7 +342,6 @@ var storesCreateFromCSVCmd = &cobra.Command{ createStoreReqParameters.Properties = props log.Debug().Msgf("Request parameters: %v", createStoreReqParameters) - // make request. log.Info().Msgf("Calling Command to create store from row '%d'", idx) res, err := kfClient.CreateStore(&createStoreReqParameters) @@ -344,6 +374,7 @@ var storesCreateFromCSVCmd = &cobra.Command{ Int("totalSuccess", totalSuccess).Send() log.Info().Msgf("Writing results to file '%s'", outPath) + //writeCsvFile(outPath, originalMap) mapToCSV(inputMap, outPath) log.Info().Int("totalRows", totalRows). @@ -1120,6 +1151,28 @@ func init() { -1, "The ID of the cert store type for the stores.", ) + storesCreateFromCSVCmd.Flags().StringVarP( + &storeTypeName, + "server-username", + "u", + "", + "The username Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column `Properties.ServerUsername`.", + ) + storesCreateFromCSVCmd.Flags().StringVarP( + &storeTypeName, + "server-password", + "p", + "", + "The password Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column `Properties.ServerPassword`.", + ) + storesCreateFromCSVCmd.Flags().StringVarP( + &storeTypeName, + "store-password", + "s", + "", + "The credential information Keyfactor Command will use to access the certificates in a specific certificate store (the store password). This is different from credential information Keyfactor Command uses to access a certificate store host. This field can be specified in the CSV file in the column `Password`.", + ) + storesCreateFromCSVCmd.Flags().StringVarP(&file, "file", "f", "", "CSV file containing cert stores to create.") storesCreateFromCSVCmd.MarkFlagRequired("file") storesCreateFromCSVCmd.Flags().BoolP("dry-run", "d", false, "Do not import, just check for necessary fields.") From de21e9090a9955ba3e571246fec5669dedcebcda Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:15:55 -0700 Subject: [PATCH 04/24] chore(docs): Regenerate docs. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- docs/kfutil.md | 2 +- docs/kfutil_completion.md | 2 +- docs/kfutil_completion_bash.md | 2 +- docs/kfutil_completion_fish.md | 2 +- docs/kfutil_completion_powershell.md | 2 +- docs/kfutil_completion_zsh.md | 2 +- docs/kfutil_containers.md | 2 +- docs/kfutil_containers_get.md | 2 +- docs/kfutil_containers_list.md | 2 +- docs/kfutil_export.md | 2 +- docs/kfutil_helm.md | 2 +- docs/kfutil_helm_uo.md | 2 +- docs/kfutil_import.md | 2 +- docs/kfutil_login.md | 2 +- docs/kfutil_logout.md | 2 +- docs/kfutil_orchs.md | 2 +- docs/kfutil_orchs_approve.md | 2 +- docs/kfutil_orchs_disapprove.md | 2 +- docs/kfutil_orchs_ext.md | 2 +- docs/kfutil_orchs_get.md | 2 +- docs/kfutil_orchs_list.md | 2 +- docs/kfutil_orchs_logs.md | 2 +- docs/kfutil_orchs_reset.md | 2 +- docs/kfutil_pam.md | 2 +- docs/kfutil_pam_create.md | 2 +- docs/kfutil_pam_delete.md | 2 +- docs/kfutil_pam_get.md | 2 +- docs/kfutil_pam_list.md | 2 +- docs/kfutil_pam_types-create.md | 2 +- docs/kfutil_pam_types-list.md | 2 +- docs/kfutil_pam_update.md | 2 +- docs/kfutil_status.md | 2 +- docs/kfutil_store-types.md | 2 +- docs/kfutil_store-types_create.md | 4 ++-- docs/kfutil_store-types_delete.md | 2 +- docs/kfutil_store-types_get.md | 2 +- docs/kfutil_store-types_list.md | 2 +- docs/kfutil_store-types_templates-fetch.md | 2 +- docs/kfutil_store-types_update.md | 2 +- docs/kfutil_stores.md | 2 +- docs/kfutil_stores_delete.md | 2 +- docs/kfutil_stores_export.md | 2 +- docs/kfutil_stores_get.md | 2 +- docs/kfutil_stores_import.md | 2 +- docs/kfutil_stores_import_csv.md | 17 ++++++++++------- docs/kfutil_stores_import_generate-template.md | 2 +- docs/kfutil_stores_inventory.md | 2 +- docs/kfutil_stores_inventory_add.md | 2 +- docs/kfutil_stores_inventory_clear.md | 2 +- docs/kfutil_stores_inventory_remove.md | 2 +- docs/kfutil_stores_inventory_show.md | 2 +- docs/kfutil_stores_list.md | 2 +- docs/kfutil_stores_rot.md | 2 +- docs/kfutil_stores_rot_audit.md | 2 +- docs/kfutil_stores_rot_generate-template.md | 2 +- docs/kfutil_stores_rot_reconcile.md | 2 +- docs/kfutil_version.md | 2 +- 57 files changed, 67 insertions(+), 64 deletions(-) diff --git a/docs/kfutil.md b/docs/kfutil.md index a7c1b0f..b3a651a 100644 --- a/docs/kfutil.md +++ b/docs/kfutil.md @@ -46,4 +46,4 @@ A CLI wrapper around the Keyfactor Platform API. * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. * [kfutil version](kfutil_version.md) - Shows version of kfutil -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_completion.md b/docs/kfutil_completion.md index 1fae919..4b8899c 100644 --- a/docs/kfutil_completion.md +++ b/docs/kfutil_completion.md @@ -45,4 +45,4 @@ See each sub-command's help for details on how to use the generated script. * [kfutil completion powershell](kfutil_completion_powershell.md) - Generate the autocompletion script for powershell * [kfutil completion zsh](kfutil_completion_zsh.md) - Generate the autocompletion script for zsh -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_completion_bash.md b/docs/kfutil_completion_bash.md index 527ddf2..a5c28f2 100644 --- a/docs/kfutil_completion_bash.md +++ b/docs/kfutil_completion_bash.md @@ -64,4 +64,4 @@ kfutil completion bash * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_completion_fish.md b/docs/kfutil_completion_fish.md index 3a32698..7fc3aa7 100644 --- a/docs/kfutil_completion_fish.md +++ b/docs/kfutil_completion_fish.md @@ -55,4 +55,4 @@ kfutil completion fish [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_completion_powershell.md b/docs/kfutil_completion_powershell.md index 50e0b78..760f70c 100644 --- a/docs/kfutil_completion_powershell.md +++ b/docs/kfutil_completion_powershell.md @@ -52,4 +52,4 @@ kfutil completion powershell [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_completion_zsh.md b/docs/kfutil_completion_zsh.md index 97c7c54..c5ec093 100644 --- a/docs/kfutil_completion_zsh.md +++ b/docs/kfutil_completion_zsh.md @@ -66,4 +66,4 @@ kfutil completion zsh [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_containers.md b/docs/kfutil_containers.md index f0624a1..0bff3f4 100644 --- a/docs/kfutil_containers.md +++ b/docs/kfutil_containers.md @@ -41,4 +41,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil containers get](kfutil_containers_get.md) - Get certificate store container by ID or name. * [kfutil containers list](kfutil_containers_list.md) - List certificate store containers. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_containers_get.md b/docs/kfutil_containers_get.md index 8b01da1..e5dbb3c 100644 --- a/docs/kfutil_containers_get.md +++ b/docs/kfutil_containers_get.md @@ -44,4 +44,4 @@ kfutil containers get [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_containers_list.md b/docs/kfutil_containers_list.md index 7a4d56d..e38523a 100644 --- a/docs/kfutil_containers_list.md +++ b/docs/kfutil_containers_list.md @@ -43,4 +43,4 @@ kfutil containers list [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_export.md b/docs/kfutil_export.md index 439e3bd..cadfe5d 100644 --- a/docs/kfutil_export.md +++ b/docs/kfutil_export.md @@ -55,4 +55,4 @@ kfutil export [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_helm.md b/docs/kfutil_helm.md index 297fa81..fec9d63 100644 --- a/docs/kfutil_helm.md +++ b/docs/kfutil_helm.md @@ -46,4 +46,4 @@ kubectl helm uo | helm install -f - keyfactor-universal-orchestrator keyfactor/k * [kfutil](kfutil.md) - Keyfactor CLI utilities * [kfutil helm uo](kfutil_helm_uo.md) - Configure the Keyfactor Universal Orchestrator Helm Chart -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_helm_uo.md b/docs/kfutil_helm_uo.md index 2471540..a56039d 100644 --- a/docs/kfutil_helm_uo.md +++ b/docs/kfutil_helm_uo.md @@ -50,4 +50,4 @@ kfutil helm uo [-t ] [-o ] [-f ] [-e -e @,@ -o ./app/extension * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_orchs_get.md b/docs/kfutil_orchs_get.md index a1fdd35..c5dd084 100644 --- a/docs/kfutil_orchs_get.md +++ b/docs/kfutil_orchs_get.md @@ -44,4 +44,4 @@ kfutil orchs get [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_orchs_list.md b/docs/kfutil_orchs_list.md index 7d28007..dc9b043 100644 --- a/docs/kfutil_orchs_list.md +++ b/docs/kfutil_orchs_list.md @@ -43,4 +43,4 @@ kfutil orchs list [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_orchs_logs.md b/docs/kfutil_orchs_logs.md index f2eb557..e98cef1 100644 --- a/docs/kfutil_orchs_logs.md +++ b/docs/kfutil_orchs_logs.md @@ -44,4 +44,4 @@ kfutil orchs logs [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_orchs_reset.md b/docs/kfutil_orchs_reset.md index fd0ebdc..aeaea25 100644 --- a/docs/kfutil_orchs_reset.md +++ b/docs/kfutil_orchs_reset.md @@ -44,4 +44,4 @@ kfutil orchs reset [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam.md b/docs/kfutil_pam.md index 0ee4a58..a05ba59 100644 --- a/docs/kfutil_pam.md +++ b/docs/kfutil_pam.md @@ -48,4 +48,4 @@ programmatically create, delete, edit, and list PAM Providers. * [kfutil pam types-list](kfutil_pam_types-list.md) - Returns a list of all available PAM provider types. * [kfutil pam update](kfutil_pam_update.md) - Updates an existing PAM Provider, currently only supported from file. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_create.md b/docs/kfutil_pam_create.md index f68938c..30c6295 100644 --- a/docs/kfutil_pam_create.md +++ b/docs/kfutil_pam_create.md @@ -44,4 +44,4 @@ kfutil pam create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_delete.md b/docs/kfutil_pam_delete.md index dbf74c0..f7e40b2 100644 --- a/docs/kfutil_pam_delete.md +++ b/docs/kfutil_pam_delete.md @@ -44,4 +44,4 @@ kfutil pam delete [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_get.md b/docs/kfutil_pam_get.md index 8bae60e..49f0844 100644 --- a/docs/kfutil_pam_get.md +++ b/docs/kfutil_pam_get.md @@ -44,4 +44,4 @@ kfutil pam get [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_list.md b/docs/kfutil_pam_list.md index e6006c7..86560fd 100644 --- a/docs/kfutil_pam_list.md +++ b/docs/kfutil_pam_list.md @@ -43,4 +43,4 @@ kfutil pam list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_types-create.md b/docs/kfutil_pam_types-create.md index 32713bb..3e83fe1 100644 --- a/docs/kfutil_pam_types-create.md +++ b/docs/kfutil_pam_types-create.md @@ -51,4 +51,4 @@ kfutil pam types-create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_types-list.md b/docs/kfutil_pam_types-list.md index d9e88af..f74607e 100644 --- a/docs/kfutil_pam_types-list.md +++ b/docs/kfutil_pam_types-list.md @@ -43,4 +43,4 @@ kfutil pam types-list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_pam_update.md b/docs/kfutil_pam_update.md index b3f7608..f3ae84e 100644 --- a/docs/kfutil_pam_update.md +++ b/docs/kfutil_pam_update.md @@ -44,4 +44,4 @@ kfutil pam update [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_status.md b/docs/kfutil_status.md index 87f0f2d..8133419 100644 --- a/docs/kfutil_status.md +++ b/docs/kfutil_status.md @@ -43,4 +43,4 @@ kfutil status [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types.md b/docs/kfutil_store-types.md index a7e15b9..b55ec31 100644 --- a/docs/kfutil_store-types.md +++ b/docs/kfutil_store-types.md @@ -44,4 +44,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil store-types list](kfutil_store-types_list.md) - List certificate store types. * [kfutil store-types templates-fetch](kfutil_store-types_templates-fetch.md) - Fetches store type templates from Keyfactor's Github. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types_create.md b/docs/kfutil_store-types_create.md index 79b7b77..78e0986 100644 --- a/docs/kfutil_store-types_create.md +++ b/docs/kfutil_store-types_create.md @@ -18,7 +18,7 @@ kfutil store-types create [flags] -b, --git-ref string The git branch or tag to reference when pulling store-types from the internet. (default "main") -h, --help help for create -l, --list List valid store types. - -n, --name string Short name of the certificate store type to get. Valid choices are: AKV, AWS-ACM, Akamai, AppGwBin, AzureApp, AzureApp2, AzureAppGw, AzureSP, AzureSP2, BIPCamera, CiscoAsa, CitrixAdc, F5-BigIQ, F5-CA-REST, F5-SL-REST, F5-WS-REST, Fortigate, GCPLoadBal, GcpCertMgr, HCVKV, HCVKVJKS, HCVKVP12, HCVKVPEM, HCVKVPFX, HCVPKI, IISU, Imperva, K8SCert, K8SCluster, K8SJKS, K8SNS, K8SPKCS12, K8SSecret, K8STLSSecr, MOST, Nmap, PaloAlto, RFDER, RFJKS, RFKDB, RFORA, RFPEM, RFPkcs12, SAMPLETYPE, Signum, VMware-NSX, WinCerMgmt, WinCert, WinSql + -n, --name string Short name of the certificate store type to get. Valid choices are: AKV, AWS-ACM, Akamai, AppGwBin, AzureApp, AzureApp2, AzureAppGw, AzureSP, AzureSP2, BIPCamera, CiscoAsa, CitrixAdc, DataPower, F5-BigIQ, F5-CA-REST, F5-SL-REST, F5-WS-REST, FortiWeb, Fortigate, GCPLoadBal, GcpCertMgr, HCVKV, HCVKVJKS, HCVKVP12, HCVKVPEM, HCVKVPFX, HCVPKI, IISU, Imperva, K8SCert, K8SCluster, K8SJKS, K8SNS, K8SPKCS12, K8SSecret, K8STLSSecr, MOST, Nmap, PaloAlto, RFDER, RFJKS, RFKDB, RFORA, RFPEM, RFPkcs12, SAMPLETYPE, Signum, VMware-NSX, WinCerMgmt, WinCert, WinSql, f5WafCa, f5WafTls, iDRAC -r, --repo string The repository to pull store-types definitions from. (default "kfutil") ``` @@ -49,4 +49,4 @@ kfutil store-types create [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types_delete.md b/docs/kfutil_store-types_delete.md index cff57c8..60a55cd 100644 --- a/docs/kfutil_store-types_delete.md +++ b/docs/kfutil_store-types_delete.md @@ -47,4 +47,4 @@ kfutil store-types delete [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types_get.md b/docs/kfutil_store-types_get.md index c1c54d8..1b29bd4 100644 --- a/docs/kfutil_store-types_get.md +++ b/docs/kfutil_store-types_get.md @@ -48,4 +48,4 @@ kfutil store-types get [-i | -n ] [-b * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types_list.md b/docs/kfutil_store-types_list.md index 1345bb1..7fb24f3 100644 --- a/docs/kfutil_store-types_list.md +++ b/docs/kfutil_store-types_list.md @@ -43,4 +43,4 @@ kfutil store-types list [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types_templates-fetch.md b/docs/kfutil_store-types_templates-fetch.md index c888ca3..26c7a87 100644 --- a/docs/kfutil_store-types_templates-fetch.md +++ b/docs/kfutil_store-types_templates-fetch.md @@ -45,4 +45,4 @@ kfutil store-types templates-fetch [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_store-types_update.md b/docs/kfutil_store-types_update.md index ab7d3ca..0b6be52 100644 --- a/docs/kfutil_store-types_update.md +++ b/docs/kfutil_store-types_update.md @@ -21,4 +21,4 @@ kfutil store-types update [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 1-Dec-2022 +###### Auto generated on 1-Dec-2022 diff --git a/docs/kfutil_stores.md b/docs/kfutil_stores.md index 570b2db..05a6074 100644 --- a/docs/kfutil_stores.md +++ b/docs/kfutil_stores.md @@ -45,4 +45,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management * [kfutil stores list](kfutil_stores_list.md) - List certificate stores. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_delete.md b/docs/kfutil_stores_delete.md index 731109b..94cb0b5 100644 --- a/docs/kfutil_stores_delete.md +++ b/docs/kfutil_stores_delete.md @@ -46,4 +46,4 @@ kfutil stores delete [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_export.md b/docs/kfutil_stores_export.md index 967bd76..b172e34 100644 --- a/docs/kfutil_stores_export.md +++ b/docs/kfutil_stores_export.md @@ -47,4 +47,4 @@ kfutil stores export [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_get.md b/docs/kfutil_stores_get.md index 19beb3d..cb06339 100644 --- a/docs/kfutil_stores_get.md +++ b/docs/kfutil_stores_get.md @@ -44,4 +44,4 @@ kfutil stores get [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_import.md b/docs/kfutil_stores_import.md index 5616626..d713b20 100644 --- a/docs/kfutil_stores_import.md +++ b/docs/kfutil_stores_import.md @@ -41,4 +41,4 @@ Tools for generating import templates and importing certificate stores * [kfutil stores import csv](kfutil_stores_import_csv.md) - Create certificate stores from CSV file. * [kfutil stores import generate-template](kfutil_stores_import_generate-template.md) - For generating a CSV template with headers for bulk store creation. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_import_csv.md b/docs/kfutil_stores_import_csv.md index 5e8237f..ba6f78c 100644 --- a/docs/kfutil_stores_import_csv.md +++ b/docs/kfutil_stores_import_csv.md @@ -16,12 +16,15 @@ kfutil stores import csv --file --store-type-id _results.csv - -i, --store-type-id int The ID of the cert store type for the stores. (default -1) - -n, --store-type-name string The name of the cert store type. Use if store-type-id is unknown. + -d, --dry-run Do not import, just check for necessary fields. + -f, --file string CSV file containing cert stores to create. + -h, --help help for csv + -o, --results-path string CSV file containing cert stores to create. defaults to _results.csv + -p, --server-password Properties.ServerPassword The password Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column Properties.ServerPassword. + -u, --server-username Properties.ServerUsername The username Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column Properties.ServerUsername. + -s, --store-password Password The credential information Keyfactor Command will use to access the certificates in a specific certificate store (the store password). This is different from credential information Keyfactor Command uses to access a certificate store host. This field can be specified in the CSV file in the column Password. + -i, --store-type-id int The ID of the cert store type for the stores. (default -1) + -n, --store-type-name string The name of the cert store type. Use if store-type-id is unknown. ``` ### Options inherited from parent commands @@ -51,4 +54,4 @@ kfutil stores import csv --file --store-type-id --store-t * [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store parameters and create them in keyfactor. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_inventory.md b/docs/kfutil_stores_inventory.md index 5445f58..a52d143 100644 --- a/docs/kfutil_stores_inventory.md +++ b/docs/kfutil_stores_inventory.md @@ -42,4 +42,4 @@ Commands related to certificate store inventory management * [kfutil stores inventory remove](kfutil_stores_inventory_remove.md) - Removes a certificate from the certificate store inventory. * [kfutil stores inventory show](kfutil_stores_inventory_show.md) - Show the inventory of a certificate store. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_inventory_add.md b/docs/kfutil_stores_inventory_add.md index d783dd5..44a8c6f 100644 --- a/docs/kfutil_stores_inventory_add.md +++ b/docs/kfutil_stores_inventory_add.md @@ -57,4 +57,4 @@ kfutil stores inventory add [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_inventory_clear.md b/docs/kfutil_stores_inventory_clear.md index fd44857..4206c40 100644 --- a/docs/kfutil_stores_inventory_clear.md +++ b/docs/kfutil_stores_inventory_clear.md @@ -37,4 +37,4 @@ kfutil stores inventory clear [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 14-Jun-2023 +###### Auto generated on 14-Jun-2023 diff --git a/docs/kfutil_stores_inventory_remove.md b/docs/kfutil_stores_inventory_remove.md index 8c00d8c..53bad39 100644 --- a/docs/kfutil_stores_inventory_remove.md +++ b/docs/kfutil_stores_inventory_remove.md @@ -53,4 +53,4 @@ kfutil stores inventory remove [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_inventory_show.md b/docs/kfutil_stores_inventory_show.md index 5c337ea..4b1dd67 100644 --- a/docs/kfutil_stores_inventory_show.md +++ b/docs/kfutil_stores_inventory_show.md @@ -47,4 +47,4 @@ kfutil stores inventory show [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_list.md b/docs/kfutil_stores_list.md index fc471da..a88e690 100644 --- a/docs/kfutil_stores_list.md +++ b/docs/kfutil_stores_list.md @@ -43,4 +43,4 @@ kfutil stores list [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 diff --git a/docs/kfutil_stores_rot.md b/docs/kfutil_stores_rot.md index ff49440..715ea0c 100644 --- a/docs/kfutil_stores_rot.md +++ b/docs/kfutil_stores_rot.md @@ -51,4 +51,4 @@ kfutil stores rot reconcile --import-csv * [kfutil stores rot generate-template](kfutil_stores_rot_generate-template.md) - For generating Root Of Trust template(s) * [kfutil stores rot reconcile](kfutil_stores_rot_reconcile.md) - Reconcile either takes in or will generate an audit report and then add/remove certs as needed. -###### Auto generated by spf13/cobra on 8-Sep-2024 +###### Auto generated on 8-Sep-2024 diff --git a/docs/kfutil_stores_rot_audit.md b/docs/kfutil_stores_rot_audit.md index 7d8a321..b9b8a3e 100644 --- a/docs/kfutil_stores_rot_audit.md +++ b/docs/kfutil_stores_rot_audit.md @@ -48,4 +48,4 @@ kfutil stores rot audit [flags] * [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated by spf13/cobra on 8-Sep-2024 +###### Auto generated on 8-Sep-2024 diff --git a/docs/kfutil_stores_rot_generate-template.md b/docs/kfutil_stores_rot_generate-template.md index 054ec02..63b5d0f 100644 --- a/docs/kfutil_stores_rot_generate-template.md +++ b/docs/kfutil_stores_rot_generate-template.md @@ -46,4 +46,4 @@ kfutil stores rot generate-template [flags] * [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated by spf13/cobra on 8-Sep-2024 +###### Auto generated on 8-Sep-2024 diff --git a/docs/kfutil_stores_rot_reconcile.md b/docs/kfutil_stores_rot_reconcile.md index 6f45ed9..a861b91 100644 --- a/docs/kfutil_stores_rot_reconcile.md +++ b/docs/kfutil_stores_rot_reconcile.md @@ -53,4 +53,4 @@ kfutil stores rot reconcile [flags] * [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated by spf13/cobra on 8-Sep-2024 +###### Auto generated on 8-Sep-2024 diff --git a/docs/kfutil_version.md b/docs/kfutil_version.md index 6df9ce0..13893cd 100644 --- a/docs/kfutil_version.md +++ b/docs/kfutil_version.md @@ -43,4 +43,4 @@ kfutil version [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated by spf13/cobra on 12-Dec-2024 +###### Auto generated on 24-Apr-2025 From 8d1e6a2462bdb75ad0a413131769c4c6ea94f127 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Sun, 27 Apr 2025 17:30:10 -0700 Subject: [PATCH 05/24] feat(stores): `import csv` supports ENV credentials. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/constants.go | 4 ++++ cmd/storesBulkOperations.go | 29 +++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/cmd/constants.go b/cmd/constants.go index 55779dd..072a16b 100644 --- a/cmd/constants.go +++ b/cmd/constants.go @@ -34,6 +34,10 @@ const ( DebugFuncExit = "exiting: %s" DebugFuncCall = "calling: %s" MinHttpTimeout = 3 + + EnvStoresImportCSVServerUsername = "KFUTIL_CSV_SERVER_USERNAME" + EnvStoresImportCSVServerPassword = "KFUTIL_CSV_SERVER_PASSWORD" + EnvStoresImportCSVStorePassword = "KFUTIL_CSV_STORE_PASSWORD" ) var ProviderTypeChoices = []string{ diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 3b5f1c6..5e340e5 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -99,7 +99,7 @@ func serializeStoreFromTypeDef(storeTypeName string, input string) (string, erro var importStoresCmd = &cobra.Command{ Use: "import", - Short: "Import a file with certificate store parameters and create them in keyfactor.", + Short: "Import a file with certificate store definitions and create them in Keyfactor Command.", Long: `Tools for generating import templates and importing certificate stores`, } @@ -121,6 +121,16 @@ var storesCreateFromCSVCmd = &cobra.Command{ serverPassword, _ := cmd.Flags().GetString("server-password") storePassword, _ := cmd.Flags().GetString("store-password") + if serverUsername == "" { + serverUsername = os.Getenv(EnvStoresImportCSVServerUsername) + } + if serverPassword == "" { + serverPassword = os.Getenv(EnvStoresImportCSVServerPassword) + } + if storePassword == "" { + storePassword = os.Getenv(EnvStoresImportCSVStorePassword) + } + //// Flag Checks //inputErr := storeTypeIdentifierFlagCheck(cmd) //if inputErr != nil { @@ -1156,21 +1166,32 @@ func init() { "server-username", "u", "", - "The username Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column `Properties.ServerUsername`.", + "The username Keyfactor Command will use to use connect to the certificate store host. "+ + "This field can be specified in the CSV file in the column `Properties.ServerUsername`. "+ + "This value can also be sourced from the environmental variable `KFUTIL_CSV_SERVER_USERNAME`. "+ + "*NOTE* a value provided in the CSV file will override any other input value", ) storesCreateFromCSVCmd.Flags().StringVarP( &storeTypeName, "server-password", "p", "", - "The password Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column `Properties.ServerPassword`.", + "The password Keyfactor Command will use to use connect to the certificate store host. "+ + "This field can be specified in the CSV file in the column `Properties.ServerPassword`. "+ + "This value can also be sourced from the environmental variable `KFUTIL_CSV_SERVER_PASSWORD`. "+ + "*NOTE* a value provided in the CSV file will override any other input value", ) storesCreateFromCSVCmd.Flags().StringVarP( &storeTypeName, "store-password", "s", "", - "The credential information Keyfactor Command will use to access the certificates in a specific certificate store (the store password). This is different from credential information Keyfactor Command uses to access a certificate store host. This field can be specified in the CSV file in the column `Password`.", + "The credential information Keyfactor Command will use to access the certificates in a specific certificate"+ + " store (the store password). This is different from credential information Keyfactor Command uses to"+ + " access a certificate store host."+ + " This field can be specified in the CSV file in the column `Password`. This value can also be sourced from"+ + " the environmental variable `KFUTIL_CSV_STORE_PASSWORD`. *NOTE* a value provided in the CSV file will"+ + " override any other input value", ) storesCreateFromCSVCmd.Flags().StringVarP(&file, "file", "f", "", "CSV file containing cert stores to create.") From 197fd751ff6a85146bc43369ee79fbf444093238 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Sun, 27 Apr 2025 17:30:35 -0700 Subject: [PATCH 06/24] chore(docs): Regenerate CLI docs Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- docs/kfutil.md | 2 +- docs/kfutil_completion.md | 2 +- docs/kfutil_completion_bash.md | 2 +- docs/kfutil_completion_fish.md | 2 +- docs/kfutil_completion_powershell.md | 2 +- docs/kfutil_completion_zsh.md | 2 +- docs/kfutil_containers.md | 2 +- docs/kfutil_containers_get.md | 2 +- docs/kfutil_containers_list.md | 2 +- docs/kfutil_export.md | 2 +- docs/kfutil_helm.md | 2 +- docs/kfutil_helm_uo.md | 2 +- docs/kfutil_import.md | 2 +- docs/kfutil_login.md | 2 +- docs/kfutil_logout.md | 2 +- docs/kfutil_orchs.md | 2 +- docs/kfutil_orchs_approve.md | 2 +- docs/kfutil_orchs_disapprove.md | 2 +- docs/kfutil_orchs_ext.md | 2 +- docs/kfutil_orchs_get.md | 2 +- docs/kfutil_orchs_list.md | 2 +- docs/kfutil_orchs_logs.md | 2 +- docs/kfutil_orchs_reset.md | 2 +- docs/kfutil_pam.md | 2 +- docs/kfutil_pam_create.md | 2 +- docs/kfutil_pam_delete.md | 2 +- docs/kfutil_pam_get.md | 2 +- docs/kfutil_pam_list.md | 2 +- docs/kfutil_pam_types-create.md | 2 +- docs/kfutil_pam_types-list.md | 2 +- docs/kfutil_pam_update.md | 2 +- docs/kfutil_status.md | 2 +- docs/kfutil_store-types.md | 2 +- docs/kfutil_store-types_create.md | 2 +- docs/kfutil_store-types_delete.md | 2 +- docs/kfutil_store-types_get.md | 2 +- docs/kfutil_store-types_list.md | 2 +- docs/kfutil_store-types_templates-fetch.md | 2 +- docs/kfutil_stores.md | 5 +++-- docs/kfutil_stores_delete.md | 2 +- docs/kfutil_stores_export.md | 2 +- docs/kfutil_stores_get.md | 2 +- docs/kfutil_stores_import.md | 4 ++-- docs/kfutil_stores_import_csv.md | 11 ++++++----- docs/kfutil_stores_import_generate-template.md | 5 +++-- docs/kfutil_stores_inventory.md | 2 +- docs/kfutil_stores_inventory_add.md | 2 +- docs/kfutil_stores_inventory_remove.md | 2 +- docs/kfutil_stores_inventory_show.md | 2 +- docs/kfutil_stores_list.md | 2 +- docs/kfutil_version.md | 2 +- 51 files changed, 61 insertions(+), 58 deletions(-) diff --git a/docs/kfutil.md b/docs/kfutil.md index b3a651a..517d253 100644 --- a/docs/kfutil.md +++ b/docs/kfutil.md @@ -46,4 +46,4 @@ A CLI wrapper around the Keyfactor Platform API. * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. * [kfutil version](kfutil_version.md) - Shows version of kfutil -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_completion.md b/docs/kfutil_completion.md index 4b8899c..6fc042b 100644 --- a/docs/kfutil_completion.md +++ b/docs/kfutil_completion.md @@ -45,4 +45,4 @@ See each sub-command's help for details on how to use the generated script. * [kfutil completion powershell](kfutil_completion_powershell.md) - Generate the autocompletion script for powershell * [kfutil completion zsh](kfutil_completion_zsh.md) - Generate the autocompletion script for zsh -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_completion_bash.md b/docs/kfutil_completion_bash.md index a5c28f2..e9f00d7 100644 --- a/docs/kfutil_completion_bash.md +++ b/docs/kfutil_completion_bash.md @@ -64,4 +64,4 @@ kfutil completion bash * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_completion_fish.md b/docs/kfutil_completion_fish.md index 7fc3aa7..9449bb1 100644 --- a/docs/kfutil_completion_fish.md +++ b/docs/kfutil_completion_fish.md @@ -55,4 +55,4 @@ kfutil completion fish [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_completion_powershell.md b/docs/kfutil_completion_powershell.md index 760f70c..75acbc8 100644 --- a/docs/kfutil_completion_powershell.md +++ b/docs/kfutil_completion_powershell.md @@ -52,4 +52,4 @@ kfutil completion powershell [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_completion_zsh.md b/docs/kfutil_completion_zsh.md index c5ec093..bd6c117 100644 --- a/docs/kfutil_completion_zsh.md +++ b/docs/kfutil_completion_zsh.md @@ -66,4 +66,4 @@ kfutil completion zsh [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_containers.md b/docs/kfutil_containers.md index 0bff3f4..d33dd36 100644 --- a/docs/kfutil_containers.md +++ b/docs/kfutil_containers.md @@ -41,4 +41,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil containers get](kfutil_containers_get.md) - Get certificate store container by ID or name. * [kfutil containers list](kfutil_containers_list.md) - List certificate store containers. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_containers_get.md b/docs/kfutil_containers_get.md index e5dbb3c..e4932c0 100644 --- a/docs/kfutil_containers_get.md +++ b/docs/kfutil_containers_get.md @@ -44,4 +44,4 @@ kfutil containers get [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_containers_list.md b/docs/kfutil_containers_list.md index e38523a..606befb 100644 --- a/docs/kfutil_containers_list.md +++ b/docs/kfutil_containers_list.md @@ -43,4 +43,4 @@ kfutil containers list [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_export.md b/docs/kfutil_export.md index cadfe5d..5f4802d 100644 --- a/docs/kfutil_export.md +++ b/docs/kfutil_export.md @@ -55,4 +55,4 @@ kfutil export [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_helm.md b/docs/kfutil_helm.md index fec9d63..7714d95 100644 --- a/docs/kfutil_helm.md +++ b/docs/kfutil_helm.md @@ -46,4 +46,4 @@ kubectl helm uo | helm install -f - keyfactor-universal-orchestrator keyfactor/k * [kfutil](kfutil.md) - Keyfactor CLI utilities * [kfutil helm uo](kfutil_helm_uo.md) - Configure the Keyfactor Universal Orchestrator Helm Chart -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_helm_uo.md b/docs/kfutil_helm_uo.md index a56039d..af9b546 100644 --- a/docs/kfutil_helm_uo.md +++ b/docs/kfutil_helm_uo.md @@ -50,4 +50,4 @@ kfutil helm uo [-t ] [-o ] [-f ] [-e -e @,@ -o ./app/extension * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_orchs_get.md b/docs/kfutil_orchs_get.md index c5dd084..1321c64 100644 --- a/docs/kfutil_orchs_get.md +++ b/docs/kfutil_orchs_get.md @@ -44,4 +44,4 @@ kfutil orchs get [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_orchs_list.md b/docs/kfutil_orchs_list.md index dc9b043..7fe5480 100644 --- a/docs/kfutil_orchs_list.md +++ b/docs/kfutil_orchs_list.md @@ -43,4 +43,4 @@ kfutil orchs list [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_orchs_logs.md b/docs/kfutil_orchs_logs.md index e98cef1..166f2ad 100644 --- a/docs/kfutil_orchs_logs.md +++ b/docs/kfutil_orchs_logs.md @@ -44,4 +44,4 @@ kfutil orchs logs [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_orchs_reset.md b/docs/kfutil_orchs_reset.md index aeaea25..c42f121 100644 --- a/docs/kfutil_orchs_reset.md +++ b/docs/kfutil_orchs_reset.md @@ -44,4 +44,4 @@ kfutil orchs reset [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam.md b/docs/kfutil_pam.md index a05ba59..d22d2f6 100644 --- a/docs/kfutil_pam.md +++ b/docs/kfutil_pam.md @@ -48,4 +48,4 @@ programmatically create, delete, edit, and list PAM Providers. * [kfutil pam types-list](kfutil_pam_types-list.md) - Returns a list of all available PAM provider types. * [kfutil pam update](kfutil_pam_update.md) - Updates an existing PAM Provider, currently only supported from file. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_create.md b/docs/kfutil_pam_create.md index 30c6295..a50d6f7 100644 --- a/docs/kfutil_pam_create.md +++ b/docs/kfutil_pam_create.md @@ -44,4 +44,4 @@ kfutil pam create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_delete.md b/docs/kfutil_pam_delete.md index f7e40b2..7a2cd5c 100644 --- a/docs/kfutil_pam_delete.md +++ b/docs/kfutil_pam_delete.md @@ -44,4 +44,4 @@ kfutil pam delete [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_get.md b/docs/kfutil_pam_get.md index 49f0844..8b624a3 100644 --- a/docs/kfutil_pam_get.md +++ b/docs/kfutil_pam_get.md @@ -44,4 +44,4 @@ kfutil pam get [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_list.md b/docs/kfutil_pam_list.md index 86560fd..656255a 100644 --- a/docs/kfutil_pam_list.md +++ b/docs/kfutil_pam_list.md @@ -43,4 +43,4 @@ kfutil pam list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_types-create.md b/docs/kfutil_pam_types-create.md index 3e83fe1..bc63a15 100644 --- a/docs/kfutil_pam_types-create.md +++ b/docs/kfutil_pam_types-create.md @@ -51,4 +51,4 @@ kfutil pam types-create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_types-list.md b/docs/kfutil_pam_types-list.md index f74607e..c5b867a 100644 --- a/docs/kfutil_pam_types-list.md +++ b/docs/kfutil_pam_types-list.md @@ -43,4 +43,4 @@ kfutil pam types-list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_pam_update.md b/docs/kfutil_pam_update.md index f3ae84e..a265853 100644 --- a/docs/kfutil_pam_update.md +++ b/docs/kfutil_pam_update.md @@ -44,4 +44,4 @@ kfutil pam update [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_status.md b/docs/kfutil_status.md index 8133419..caf691b 100644 --- a/docs/kfutil_status.md +++ b/docs/kfutil_status.md @@ -43,4 +43,4 @@ kfutil status [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_store-types.md b/docs/kfutil_store-types.md index b55ec31..45babc0 100644 --- a/docs/kfutil_store-types.md +++ b/docs/kfutil_store-types.md @@ -44,4 +44,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil store-types list](kfutil_store-types_list.md) - List certificate store types. * [kfutil store-types templates-fetch](kfutil_store-types_templates-fetch.md) - Fetches store type templates from Keyfactor's Github. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_store-types_create.md b/docs/kfutil_store-types_create.md index 78e0986..2ace09f 100644 --- a/docs/kfutil_store-types_create.md +++ b/docs/kfutil_store-types_create.md @@ -49,4 +49,4 @@ kfutil store-types create [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_store-types_delete.md b/docs/kfutil_store-types_delete.md index 60a55cd..fb8822d 100644 --- a/docs/kfutil_store-types_delete.md +++ b/docs/kfutil_store-types_delete.md @@ -47,4 +47,4 @@ kfutil store-types delete [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_store-types_get.md b/docs/kfutil_store-types_get.md index 1b29bd4..be679a4 100644 --- a/docs/kfutil_store-types_get.md +++ b/docs/kfutil_store-types_get.md @@ -48,4 +48,4 @@ kfutil store-types get [-i | -n ] [-b * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_store-types_list.md b/docs/kfutil_store-types_list.md index 7fb24f3..bf2f8f1 100644 --- a/docs/kfutil_store-types_list.md +++ b/docs/kfutil_store-types_list.md @@ -43,4 +43,4 @@ kfutil store-types list [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_store-types_templates-fetch.md b/docs/kfutil_store-types_templates-fetch.md index 26c7a87..70e4e95 100644 --- a/docs/kfutil_store-types_templates-fetch.md +++ b/docs/kfutil_store-types_templates-fetch.md @@ -45,4 +45,4 @@ kfutil store-types templates-fetch [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores.md b/docs/kfutil_stores.md index 05a6074..f5a913d 100644 --- a/docs/kfutil_stores.md +++ b/docs/kfutil_stores.md @@ -41,8 +41,9 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil stores delete](kfutil_stores_delete.md) - Delete a certificate store by ID. * [kfutil stores export](kfutil_stores_export.md) - Export existing defined certificate stores by type or store Id. * [kfutil stores get](kfutil_stores_get.md) - Get a certificate store by ID. -* [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store parameters and create them in keyfactor. +* [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store definitions and create them + in Keyfactor Command. * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management * [kfutil stores list](kfutil_stores_list.md) - List certificate stores. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_delete.md b/docs/kfutil_stores_delete.md index 94cb0b5..429d2ad 100644 --- a/docs/kfutil_stores_delete.md +++ b/docs/kfutil_stores_delete.md @@ -46,4 +46,4 @@ kfutil stores delete [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_export.md b/docs/kfutil_stores_export.md index b172e34..84d68c7 100644 --- a/docs/kfutil_stores_export.md +++ b/docs/kfutil_stores_export.md @@ -47,4 +47,4 @@ kfutil stores export [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_get.md b/docs/kfutil_stores_get.md index cb06339..54187fc 100644 --- a/docs/kfutil_stores_get.md +++ b/docs/kfutil_stores_get.md @@ -44,4 +44,4 @@ kfutil stores get [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_import.md b/docs/kfutil_stores_import.md index d713b20..500664d 100644 --- a/docs/kfutil_stores_import.md +++ b/docs/kfutil_stores_import.md @@ -1,6 +1,6 @@ ## kfutil stores import -Import a file with certificate store parameters and create them in keyfactor. +Import a file with certificate store definitions and create them in Keyfactor Command. ### Synopsis @@ -41,4 +41,4 @@ Tools for generating import templates and importing certificate stores * [kfutil stores import csv](kfutil_stores_import_csv.md) - Create certificate stores from CSV file. * [kfutil stores import generate-template](kfutil_stores_import_generate-template.md) - For generating a CSV template with headers for bulk store creation. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_import_csv.md b/docs/kfutil_stores_import_csv.md index ba6f78c..1400ab3 100644 --- a/docs/kfutil_stores_import_csv.md +++ b/docs/kfutil_stores_import_csv.md @@ -20,9 +20,9 @@ kfutil stores import csv --file --store-type-id _results.csv - -p, --server-password Properties.ServerPassword The password Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column Properties.ServerPassword. - -u, --server-username Properties.ServerUsername The username Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column Properties.ServerUsername. - -s, --store-password Password The credential information Keyfactor Command will use to access the certificates in a specific certificate store (the store password). This is different from credential information Keyfactor Command uses to access a certificate store host. This field can be specified in the CSV file in the column Password. + -p, --server-password Properties.ServerPassword The password Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column Properties.ServerPassword. This value can also be sourced from the environmental variable `KFUTIL_CSV_SERVER_PASSWORD`. *NOTE* a value provided in the CSV file will override any other input value + -u, --server-username Properties.ServerUsername The username Keyfactor Command will use to use connect to the certificate store host. This field can be specified in the CSV file in the column Properties.ServerUsername. This value can also be sourced from the environmental variable `KFUTIL_CSV_SERVER_USERNAME`. *NOTE* a value provided in the CSV file will override any other input value + -s, --store-password Password The credential information Keyfactor Command will use to access the certificates in a specific certificate store (the store password). This is different from credential information Keyfactor Command uses to access a certificate store host. This field can be specified in the CSV file in the column Password. This value can also be sourced from the environmental variable `KFUTIL_CSV_STORE_PASSWORD`. *NOTE* a value provided in the CSV file will override any other input value -i, --store-type-id int The ID of the cert store type for the stores. (default -1) -n, --store-type-name string The name of the cert store type. Use if store-type-id is unknown. ``` @@ -52,6 +52,7 @@ kfutil stores import csv --file --store-type-id --store-t ### SEE ALSO -* [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store parameters and create them in keyfactor. +* [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store definitions and create them + in Keyfactor Command. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_inventory.md b/docs/kfutil_stores_inventory.md index a52d143..87ebf93 100644 --- a/docs/kfutil_stores_inventory.md +++ b/docs/kfutil_stores_inventory.md @@ -42,4 +42,4 @@ Commands related to certificate store inventory management * [kfutil stores inventory remove](kfutil_stores_inventory_remove.md) - Removes a certificate from the certificate store inventory. * [kfutil stores inventory show](kfutil_stores_inventory_show.md) - Show the inventory of a certificate store. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_inventory_add.md b/docs/kfutil_stores_inventory_add.md index 44a8c6f..8e9cf0d 100644 --- a/docs/kfutil_stores_inventory_add.md +++ b/docs/kfutil_stores_inventory_add.md @@ -57,4 +57,4 @@ kfutil stores inventory add [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_inventory_remove.md b/docs/kfutil_stores_inventory_remove.md index 53bad39..6b84543 100644 --- a/docs/kfutil_stores_inventory_remove.md +++ b/docs/kfutil_stores_inventory_remove.md @@ -53,4 +53,4 @@ kfutil stores inventory remove [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_inventory_show.md b/docs/kfutil_stores_inventory_show.md index 4b1dd67..9370d9e 100644 --- a/docs/kfutil_stores_inventory_show.md +++ b/docs/kfutil_stores_inventory_show.md @@ -47,4 +47,4 @@ kfutil stores inventory show [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_stores_list.md b/docs/kfutil_stores_list.md index a88e690..df2c94a 100644 --- a/docs/kfutil_stores_list.md +++ b/docs/kfutil_stores_list.md @@ -43,4 +43,4 @@ kfutil stores list [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 diff --git a/docs/kfutil_version.md b/docs/kfutil_version.md index 13893cd..ae6fa1c 100644 --- a/docs/kfutil_version.md +++ b/docs/kfutil_version.md @@ -43,4 +43,4 @@ kfutil version [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated on 24-Apr-2025 +###### Auto generated on 27-Apr-2025 From 8d1b82feb3b281dc7ebb884eccfa4abb2fd0bb65 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Sun, 27 Apr 2025 17:30:49 -0700 Subject: [PATCH 07/24] chore(docs): Update CHANGELOG.md Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60bbcab..5addb0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +# v1.7.0 + +## Features + +### CLI + +- `stores import csv`: supports interactive credential input, as well as input via flags and environmental + variables. [docs](docs/kfutil_stores_import_csv.md) + +## Fixes + +### CLI + +- `stores import csv`: providing a `Password(/StorePassword)` does not crash CLI. +- `stores import csv`: results CSV retains input header ordering. + # v1.6.2 ## Fixes From be591a2498694e54dc5ae49bd9b52a6bd94f03ae Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Sun, 27 Apr 2025 17:40:51 -0700 Subject: [PATCH 08/24] chore(docs): Update `stores import csv` top level synopsis with credential input options Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 7 ++++++- docs/kfutil_stores_import_csv.md | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 5e340e5..923ab76 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -109,7 +109,12 @@ var storesCreateFromCSVCmd = &cobra.Command{ Long: `Certificate stores: Will parse a CSV and attempt to create a certificate store for each row with the provided parameters. 'store-type-name' OR 'store-type-id' are required. 'file' is the path to the file to be imported. -'resultspath' is where the import results will be written to.`, +'resultspath' is where the import results will be written to. +*NOTE*: If you do not wish to include credentials in your CSV file they can be provided one of three ways: +- via the --server-username --server-password and --store-password flags +- via environment variables: KFUTIL_CSV_SERVER_USERNAME, KFUTIL_CSV_SERVER_PASSWORD, KFUTIL_CSV_STORE_PASSWORD +- via interactive prompts +`, RunE: func(cmd *cobra.Command, args []string) error { // Specific flags storeTypeName, _ := cmd.Flags().GetString("store-type-name") diff --git a/docs/kfutil_stores_import_csv.md b/docs/kfutil_stores_import_csv.md index 1400ab3..7ef2f67 100644 --- a/docs/kfutil_stores_import_csv.md +++ b/docs/kfutil_stores_import_csv.md @@ -8,6 +8,11 @@ Certificate stores: Will parse a CSV and attempt to create a certificate store f 'store-type-name' OR 'store-type-id' are required. 'file' is the path to the file to be imported. 'resultspath' is where the import results will be written to. +*NOTE*: If you do not wish to include credentials in your CSV file they can be provided one of three ways: + +- via the --server-username --server-password and --store-password flags +- via environment variables: KFUTIL_CSV_SERVER_USERNAME, KFUTIL_CSV_SERVER_PASSWORD, KFUTIL_CSV_STORE_PASSWORD +- via interactive prompts ``` kfutil stores import csv --file --store-type-id --store-type-name --results-path --dry-run [flags] From b10de54305efd138a9234b0e208a020347b0f239 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Tue, 29 Apr 2025 09:35:37 -0700 Subject: [PATCH 09/24] chore(docs): Update `stores import csv` top level synopsis with mapping table for credential fields. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 24 +++++++++++++---- docs/kfutil.md | 2 +- docs/kfutil_completion.md | 2 +- docs/kfutil_completion_bash.md | 2 +- docs/kfutil_completion_fish.md | 2 +- docs/kfutil_completion_powershell.md | 2 +- docs/kfutil_completion_zsh.md | 2 +- docs/kfutil_containers.md | 2 +- docs/kfutil_containers_get.md | 2 +- docs/kfutil_containers_list.md | 2 +- docs/kfutil_export.md | 2 +- docs/kfutil_helm.md | 2 +- docs/kfutil_helm_uo.md | 2 +- docs/kfutil_import.md | 2 +- docs/kfutil_login.md | 2 +- docs/kfutil_logout.md | 2 +- docs/kfutil_orchs.md | 2 +- docs/kfutil_orchs_approve.md | 2 +- docs/kfutil_orchs_disapprove.md | 2 +- docs/kfutil_orchs_ext.md | 2 +- docs/kfutil_orchs_get.md | 2 +- docs/kfutil_orchs_list.md | 2 +- docs/kfutil_orchs_logs.md | 2 +- docs/kfutil_orchs_reset.md | 2 +- docs/kfutil_pam.md | 2 +- docs/kfutil_pam_create.md | 2 +- docs/kfutil_pam_delete.md | 2 +- docs/kfutil_pam_get.md | 2 +- docs/kfutil_pam_list.md | 2 +- docs/kfutil_pam_types-create.md | 2 +- docs/kfutil_pam_types-list.md | 2 +- docs/kfutil_pam_update.md | 2 +- docs/kfutil_status.md | 2 +- docs/kfutil_store-types.md | 2 +- docs/kfutil_store-types_create.md | 2 +- docs/kfutil_store-types_delete.md | 2 +- docs/kfutil_store-types_get.md | 2 +- docs/kfutil_store-types_list.md | 2 +- docs/kfutil_store-types_templates-fetch.md | 2 +- docs/kfutil_stores.md | 2 +- docs/kfutil_stores_delete.md | 2 +- docs/kfutil_stores_export.md | 2 +- docs/kfutil_stores_get.md | 2 +- docs/kfutil_stores_import.md | 2 +- docs/kfutil_stores_import_csv.md | 27 ++++++++++++++----- .../kfutil_stores_import_generate-template.md | 2 +- docs/kfutil_stores_inventory.md | 2 +- docs/kfutil_stores_inventory_add.md | 2 +- docs/kfutil_stores_inventory_remove.md | 2 +- docs/kfutil_stores_inventory_show.md | 2 +- docs/kfutil_stores_list.md | 2 +- docs/kfutil_version.md | 2 +- 52 files changed, 90 insertions(+), 61 deletions(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 923ab76..7fca540 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -106,11 +106,25 @@ var importStoresCmd = &cobra.Command{ var storesCreateFromCSVCmd = &cobra.Command{ Use: "csv --file --store-type-id --store-type-name --results-path --dry-run ", Short: "Create certificate stores from CSV file.", - Long: `Certificate stores: Will parse a CSV and attempt to create a certificate store for each row with the provided parameters. -'store-type-name' OR 'store-type-id' are required. -'file' is the path to the file to be imported. -'resultspath' is where the import results will be written to. -*NOTE*: If you do not wish to include credentials in your CSV file they can be provided one of three ways: + Long: `Will parse a CSV file and attempt to create a certificate store for each row with the provided parameters. +Any errors encountered will be logged to the _results.csv file, under the 'Errors' column. + +Required Flags: +- '--store-type-name' OR '--store-type-id' +- '--file' is the path to the file to be imported. + +#### Credentials + +##### In the CSV file: + +| Header | Description | +| --- | --- | +| Properties.ServerUsername | This is equivalent to the 'ServerUsername' field in the Command Certificate Store UI. | +| Properties.ServerPassword | This is equivalent to the 'ServerPassword' field in the Command Certificate Store UI. | +| Password | This is equivalent to the 'StorePassword' field in the Command Certificate Store UI. | + +##### Outside CSV file: +If you do not wish to include credentials in your CSV file they can be provided one of three ways: - via the --server-username --server-password and --store-password flags - via environment variables: KFUTIL_CSV_SERVER_USERNAME, KFUTIL_CSV_SERVER_PASSWORD, KFUTIL_CSV_STORE_PASSWORD - via interactive prompts diff --git a/docs/kfutil.md b/docs/kfutil.md index 517d253..d7e91aa 100644 --- a/docs/kfutil.md +++ b/docs/kfutil.md @@ -46,4 +46,4 @@ A CLI wrapper around the Keyfactor Platform API. * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. * [kfutil version](kfutil_version.md) - Shows version of kfutil -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_completion.md b/docs/kfutil_completion.md index 6fc042b..bc2b115 100644 --- a/docs/kfutil_completion.md +++ b/docs/kfutil_completion.md @@ -45,4 +45,4 @@ See each sub-command's help for details on how to use the generated script. * [kfutil completion powershell](kfutil_completion_powershell.md) - Generate the autocompletion script for powershell * [kfutil completion zsh](kfutil_completion_zsh.md) - Generate the autocompletion script for zsh -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_completion_bash.md b/docs/kfutil_completion_bash.md index e9f00d7..f3e095a 100644 --- a/docs/kfutil_completion_bash.md +++ b/docs/kfutil_completion_bash.md @@ -64,4 +64,4 @@ kfutil completion bash * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_completion_fish.md b/docs/kfutil_completion_fish.md index 9449bb1..f92d133 100644 --- a/docs/kfutil_completion_fish.md +++ b/docs/kfutil_completion_fish.md @@ -55,4 +55,4 @@ kfutil completion fish [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_completion_powershell.md b/docs/kfutil_completion_powershell.md index 75acbc8..24c9894 100644 --- a/docs/kfutil_completion_powershell.md +++ b/docs/kfutil_completion_powershell.md @@ -52,4 +52,4 @@ kfutil completion powershell [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_completion_zsh.md b/docs/kfutil_completion_zsh.md index bd6c117..fb3ca06 100644 --- a/docs/kfutil_completion_zsh.md +++ b/docs/kfutil_completion_zsh.md @@ -66,4 +66,4 @@ kfutil completion zsh [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_containers.md b/docs/kfutil_containers.md index d33dd36..5af7d38 100644 --- a/docs/kfutil_containers.md +++ b/docs/kfutil_containers.md @@ -41,4 +41,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil containers get](kfutil_containers_get.md) - Get certificate store container by ID or name. * [kfutil containers list](kfutil_containers_list.md) - List certificate store containers. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_containers_get.md b/docs/kfutil_containers_get.md index e4932c0..96389a4 100644 --- a/docs/kfutil_containers_get.md +++ b/docs/kfutil_containers_get.md @@ -44,4 +44,4 @@ kfutil containers get [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_containers_list.md b/docs/kfutil_containers_list.md index 606befb..ca31b47 100644 --- a/docs/kfutil_containers_list.md +++ b/docs/kfutil_containers_list.md @@ -43,4 +43,4 @@ kfutil containers list [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_export.md b/docs/kfutil_export.md index 5f4802d..992468c 100644 --- a/docs/kfutil_export.md +++ b/docs/kfutil_export.md @@ -55,4 +55,4 @@ kfutil export [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_helm.md b/docs/kfutil_helm.md index 7714d95..f20eab0 100644 --- a/docs/kfutil_helm.md +++ b/docs/kfutil_helm.md @@ -46,4 +46,4 @@ kubectl helm uo | helm install -f - keyfactor-universal-orchestrator keyfactor/k * [kfutil](kfutil.md) - Keyfactor CLI utilities * [kfutil helm uo](kfutil_helm_uo.md) - Configure the Keyfactor Universal Orchestrator Helm Chart -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_helm_uo.md b/docs/kfutil_helm_uo.md index af9b546..9e1ef98 100644 --- a/docs/kfutil_helm_uo.md +++ b/docs/kfutil_helm_uo.md @@ -50,4 +50,4 @@ kfutil helm uo [-t ] [-o ] [-f ] [-e -e @,@ -o ./app/extension * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_orchs_get.md b/docs/kfutil_orchs_get.md index 1321c64..35c428a 100644 --- a/docs/kfutil_orchs_get.md +++ b/docs/kfutil_orchs_get.md @@ -44,4 +44,4 @@ kfutil orchs get [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_orchs_list.md b/docs/kfutil_orchs_list.md index 7fe5480..4a19313 100644 --- a/docs/kfutil_orchs_list.md +++ b/docs/kfutil_orchs_list.md @@ -43,4 +43,4 @@ kfutil orchs list [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_orchs_logs.md b/docs/kfutil_orchs_logs.md index 166f2ad..65ab207 100644 --- a/docs/kfutil_orchs_logs.md +++ b/docs/kfutil_orchs_logs.md @@ -44,4 +44,4 @@ kfutil orchs logs [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_orchs_reset.md b/docs/kfutil_orchs_reset.md index c42f121..dcd1384 100644 --- a/docs/kfutil_orchs_reset.md +++ b/docs/kfutil_orchs_reset.md @@ -44,4 +44,4 @@ kfutil orchs reset [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam.md b/docs/kfutil_pam.md index d22d2f6..5399a80 100644 --- a/docs/kfutil_pam.md +++ b/docs/kfutil_pam.md @@ -48,4 +48,4 @@ programmatically create, delete, edit, and list PAM Providers. * [kfutil pam types-list](kfutil_pam_types-list.md) - Returns a list of all available PAM provider types. * [kfutil pam update](kfutil_pam_update.md) - Updates an existing PAM Provider, currently only supported from file. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_create.md b/docs/kfutil_pam_create.md index a50d6f7..35eaf32 100644 --- a/docs/kfutil_pam_create.md +++ b/docs/kfutil_pam_create.md @@ -44,4 +44,4 @@ kfutil pam create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_delete.md b/docs/kfutil_pam_delete.md index 7a2cd5c..594f3d7 100644 --- a/docs/kfutil_pam_delete.md +++ b/docs/kfutil_pam_delete.md @@ -44,4 +44,4 @@ kfutil pam delete [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_get.md b/docs/kfutil_pam_get.md index 8b624a3..3bb7c23 100644 --- a/docs/kfutil_pam_get.md +++ b/docs/kfutil_pam_get.md @@ -44,4 +44,4 @@ kfutil pam get [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_list.md b/docs/kfutil_pam_list.md index 656255a..3f58dc6 100644 --- a/docs/kfutil_pam_list.md +++ b/docs/kfutil_pam_list.md @@ -43,4 +43,4 @@ kfutil pam list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_types-create.md b/docs/kfutil_pam_types-create.md index bc63a15..f8dcd92 100644 --- a/docs/kfutil_pam_types-create.md +++ b/docs/kfutil_pam_types-create.md @@ -51,4 +51,4 @@ kfutil pam types-create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_types-list.md b/docs/kfutil_pam_types-list.md index c5b867a..01314a7 100644 --- a/docs/kfutil_pam_types-list.md +++ b/docs/kfutil_pam_types-list.md @@ -43,4 +43,4 @@ kfutil pam types-list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_pam_update.md b/docs/kfutil_pam_update.md index a265853..6c78b7d 100644 --- a/docs/kfutil_pam_update.md +++ b/docs/kfutil_pam_update.md @@ -44,4 +44,4 @@ kfutil pam update [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_status.md b/docs/kfutil_status.md index caf691b..20ce403 100644 --- a/docs/kfutil_status.md +++ b/docs/kfutil_status.md @@ -43,4 +43,4 @@ kfutil status [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_store-types.md b/docs/kfutil_store-types.md index 45babc0..7b35c1b 100644 --- a/docs/kfutil_store-types.md +++ b/docs/kfutil_store-types.md @@ -44,4 +44,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil store-types list](kfutil_store-types_list.md) - List certificate store types. * [kfutil store-types templates-fetch](kfutil_store-types_templates-fetch.md) - Fetches store type templates from Keyfactor's Github. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_store-types_create.md b/docs/kfutil_store-types_create.md index 2ace09f..e8564f6 100644 --- a/docs/kfutil_store-types_create.md +++ b/docs/kfutil_store-types_create.md @@ -49,4 +49,4 @@ kfutil store-types create [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_store-types_delete.md b/docs/kfutil_store-types_delete.md index fb8822d..67f5920 100644 --- a/docs/kfutil_store-types_delete.md +++ b/docs/kfutil_store-types_delete.md @@ -47,4 +47,4 @@ kfutil store-types delete [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_store-types_get.md b/docs/kfutil_store-types_get.md index be679a4..756f0a8 100644 --- a/docs/kfutil_store-types_get.md +++ b/docs/kfutil_store-types_get.md @@ -48,4 +48,4 @@ kfutil store-types get [-i | -n ] [-b * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_store-types_list.md b/docs/kfutil_store-types_list.md index bf2f8f1..a132026 100644 --- a/docs/kfutil_store-types_list.md +++ b/docs/kfutil_store-types_list.md @@ -43,4 +43,4 @@ kfutil store-types list [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_store-types_templates-fetch.md b/docs/kfutil_store-types_templates-fetch.md index 70e4e95..d5d4385 100644 --- a/docs/kfutil_store-types_templates-fetch.md +++ b/docs/kfutil_store-types_templates-fetch.md @@ -45,4 +45,4 @@ kfutil store-types templates-fetch [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores.md b/docs/kfutil_stores.md index f5a913d..e10e96e 100644 --- a/docs/kfutil_stores.md +++ b/docs/kfutil_stores.md @@ -46,4 +46,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management * [kfutil stores list](kfutil_stores_list.md) - List certificate stores. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_delete.md b/docs/kfutil_stores_delete.md index 429d2ad..9f934f9 100644 --- a/docs/kfutil_stores_delete.md +++ b/docs/kfutil_stores_delete.md @@ -46,4 +46,4 @@ kfutil stores delete [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_export.md b/docs/kfutil_stores_export.md index 84d68c7..0b8557e 100644 --- a/docs/kfutil_stores_export.md +++ b/docs/kfutil_stores_export.md @@ -47,4 +47,4 @@ kfutil stores export [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_get.md b/docs/kfutil_stores_get.md index 54187fc..5545c0b 100644 --- a/docs/kfutil_stores_get.md +++ b/docs/kfutil_stores_get.md @@ -44,4 +44,4 @@ kfutil stores get [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_import.md b/docs/kfutil_stores_import.md index 500664d..337505f 100644 --- a/docs/kfutil_stores_import.md +++ b/docs/kfutil_stores_import.md @@ -41,4 +41,4 @@ Tools for generating import templates and importing certificate stores * [kfutil stores import csv](kfutil_stores_import_csv.md) - Create certificate stores from CSV file. * [kfutil stores import generate-template](kfutil_stores_import_generate-template.md) - For generating a CSV template with headers for bulk store creation. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_import_csv.md b/docs/kfutil_stores_import_csv.md index 7ef2f67..908080c 100644 --- a/docs/kfutil_stores_import_csv.md +++ b/docs/kfutil_stores_import_csv.md @@ -4,16 +4,31 @@ Create certificate stores from CSV file. ### Synopsis -Certificate stores: Will parse a CSV and attempt to create a certificate store for each row with the provided parameters. -'store-type-name' OR 'store-type-id' are required. -'file' is the path to the file to be imported. -'resultspath' is where the import results will be written to. -*NOTE*: If you do not wish to include credentials in your CSV file they can be provided one of three ways: +Will parse a CSV file and attempt to create a certificate store for each row with the provided parameters. +Any errors encountered will be logged to the _results.csv file, under the 'Errors' column. +Required Flags: + +- '--store-type-name' OR '--store-type-id' +- '--file' is the path to the file to be imported. + +#### Credentials + +##### In the CSV file: + +| Header | Description | +|---------------------------|---------------------------------------------------------------------------------------| +| Properties.ServerUsername | This is equivalent to the 'ServerUsername' field in the Command Certificate Store UI. | +| Properties.ServerPassword | This is equivalent to the 'ServerPassword' field in the Command Certificate Store UI. | +| Password | This is equivalent to the 'StorePassword' field in the Command Certificate Store UI. | + +##### Outside CSV file: +If you do not wish to include credentials in your CSV file they can be provided one of three ways: - via the --server-username --server-password and --store-password flags - via environment variables: KFUTIL_CSV_SERVER_USERNAME, KFUTIL_CSV_SERVER_PASSWORD, KFUTIL_CSV_STORE_PASSWORD - via interactive prompts + ``` kfutil stores import csv --file --store-type-id --store-type-name --results-path --dry-run [flags] ``` @@ -60,4 +75,4 @@ kfutil stores import csv --file --store-type-id --store-t * [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store definitions and create them in Keyfactor Command. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_inventory.md b/docs/kfutil_stores_inventory.md index 87ebf93..3d1256a 100644 --- a/docs/kfutil_stores_inventory.md +++ b/docs/kfutil_stores_inventory.md @@ -42,4 +42,4 @@ Commands related to certificate store inventory management * [kfutil stores inventory remove](kfutil_stores_inventory_remove.md) - Removes a certificate from the certificate store inventory. * [kfutil stores inventory show](kfutil_stores_inventory_show.md) - Show the inventory of a certificate store. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_inventory_add.md b/docs/kfutil_stores_inventory_add.md index 8e9cf0d..9e9b392 100644 --- a/docs/kfutil_stores_inventory_add.md +++ b/docs/kfutil_stores_inventory_add.md @@ -57,4 +57,4 @@ kfutil stores inventory add [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_inventory_remove.md b/docs/kfutil_stores_inventory_remove.md index 6b84543..90d2abc 100644 --- a/docs/kfutil_stores_inventory_remove.md +++ b/docs/kfutil_stores_inventory_remove.md @@ -53,4 +53,4 @@ kfutil stores inventory remove [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_inventory_show.md b/docs/kfutil_stores_inventory_show.md index 9370d9e..5f5efbf 100644 --- a/docs/kfutil_stores_inventory_show.md +++ b/docs/kfutil_stores_inventory_show.md @@ -47,4 +47,4 @@ kfutil stores inventory show [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_stores_list.md b/docs/kfutil_stores_list.md index df2c94a..20deef0 100644 --- a/docs/kfutil_stores_list.md +++ b/docs/kfutil_stores_list.md @@ -43,4 +43,4 @@ kfutil stores list [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 diff --git a/docs/kfutil_version.md b/docs/kfutil_version.md index ae6fa1c..36d6180 100644 --- a/docs/kfutil_version.md +++ b/docs/kfutil_version.md @@ -43,4 +43,4 @@ kfutil version [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated on 27-Apr-2025 +###### Auto generated by spf13/cobra on 29-Apr-2025 From 436c6ea722e8761d21f3f4a27df825ef9a4b3ec6 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Tue, 6 May 2025 18:26:05 -0700 Subject: [PATCH 10/24] fix(stores): When creating a store don't log the request. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 7fca540..595ffc9 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -1062,8 +1062,6 @@ func getJsonForRequest(headerRow []string, row []string) *gabs.Container { } } } - //fmt.Printf("[DEBUG] get JSON for create store request: %s", reqJson.String()) - log.Debug().Msgf("JSON for create store request: %s", reqJson.String()) return reqJson } From b498ac63fd0d6a4722dfd78495d624c7c6a48b35 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 7 May 2025 08:10:58 -0700 Subject: [PATCH 11/24] fix(cli): Escape git branch refs for online store-type lookups. fix(cli): fetch valid store-types from after logging is initialized. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storeTypes.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/storeTypes.go b/cmd/storeTypes.go index 20e43f0..4151d91 100644 --- a/cmd/storeTypes.go +++ b/cmd/storeTypes.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "net/http" + "net/url" "os" "sort" "strings" @@ -93,7 +94,6 @@ var storesTypeCreateCmd = &cobra.Command{ gitRef, _ := cmd.Flags().GetString(FlagGitRef) gitRepo, _ := cmd.Flags().GetString(FlagGitRepo) creatAll, _ := cmd.Flags().GetBool("all") - validStoreTypes := getValidStoreTypes("", gitRef, gitRepo) storeType, _ := cmd.Flags().GetString("name") listTypes, _ := cmd.Flags().GetBool("list") storeTypeConfigFile, _ := cmd.Flags().GetString("from-file") @@ -106,6 +106,8 @@ var storesTypeCreateCmd = &cobra.Command{ } informDebug(debugFlag) + validStoreTypes := getValidStoreTypes("", gitRef, gitRepo) + // Authenticate kfClient, _ := initClient(false) @@ -505,7 +507,8 @@ func getStoreTypesInternet(gitRef string, repo string) (map[string]interface{}, fileName = "integration-manifest.json" } - url := fmt.Sprintf(baseUrl, repo, gitRef, fileName) + escapedGitRef := url.PathEscape(gitRef) + url := fmt.Sprintf(baseUrl, repo, escapedGitRef, fileName) log.Debug(). Str("url", url). Msg("Getting store types from internet") From 04d84bd710e0cd7fb8fe33ca707b84d0f3c01d8e Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 7 May 2025 08:32:05 -0700 Subject: [PATCH 12/24] chore(docs): Update CHANGELOG.md Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5addb0f..11cd075 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ - `stores import csv`: providing a `Password(/StorePassword)` does not crash CLI. - `stores import csv`: results CSV retains input header ordering. +- `store-types create`: URL encode `-b` parameter when passed. +- `store-types create`: Initialize logger before fetching store-type definitions # v1.6.2 From 8a1c308c81b1f0fe84bb37297e4f56f22235a12b Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 7 May 2025 14:06:28 -0700 Subject: [PATCH 13/24] fix(cli): `stores import csv` strip all `BOM`s from payload. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 595ffc9..6441fb3 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -47,6 +47,12 @@ var ( } ) +const bom = "\uFEFF" + +func stripAllBOMs(s string) string { + return strings.ReplaceAll(s, bom, "") +} + // formatProperties will iterate through the properties of a json object and convert any "int" values to strings // this is required because the Keyfactor API expects all properties to be strings func formatProperties(json *gabs.Container, reqPropertiesForStoreType []string) *gabs.Container { @@ -355,7 +361,7 @@ If you do not wish to include credentials in your CSV file they can be provided Value: &storePassword, } } - mJSON := reqJson.String() + mJSON := stripAllBOMs(reqJson.String()) conversionError := json.Unmarshal([]byte(mJSON), &createStoreReqParameters) if conversionError != nil { From c126d75860ccdf0a2fd7ccf74685c5d418a71651 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 7 May 2025 14:44:18 -0700 Subject: [PATCH 14/24] fix(cli): `stores import csv` strip all `BOM`s from payload. feat(cli): `stores import csv` preserve header order in `_results.csv` Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/helpers.go | 28 +++++++++++++++++----------- cmd/storesBulkOperations.go | 4 +++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/cmd/helpers.go b/cmd/helpers.go index 52e0cdb..2a4bc1f 100644 --- a/cmd/helpers.go +++ b/cmd/helpers.go @@ -23,6 +23,7 @@ import ( "net/http" "os" "path/filepath" + "slices" "strconv" "time" @@ -132,7 +133,7 @@ func csvToMap(filename string) ([]map[string]string, error) { // Populate the map with data from the row for i, column := range header { - rowMap[column] = row[i] + rowMap[column] = stripAllBOMs(row[i]) } // Append the map to the data slice @@ -282,10 +283,10 @@ func logGlobals() { } -func mapToCSV(data []map[string]string, filename string) error { - file, err := os.Create(filename) - if err != nil { - return err +func mapToCSV(data []map[string]string, filename string, inputHeader []string) error { + file, fErr := os.Create(filename) + if fErr != nil { + return fErr } defer file.Close() @@ -293,16 +294,21 @@ func mapToCSV(data []map[string]string, filename string) error { defer writer.Flush() // Write the header using keys from the first map - var header []string - if len(data) > 0 { + var header = inputHeader + if len(header) <= 0 && len(data) > 0 { for key := range data[0] { - header = append(header, key) - } - if err := writer.Write(header); err != nil { - return err + header = append(header, stripAllBOMs(key)) } } + errorColFound := slices.Contains(header, "Errors") + if !errorColFound { + header = append(header, "Errors") + } + if hErr := writer.Write(header); hErr != nil { + return hErr + } + // Write map data to CSV for _, row := range data { var record []string diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 6441fb3..230318c 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -311,12 +311,14 @@ If you do not wish to include credentials in your CSV file they can be provided } log.Info().Msgf("Processing CSV rows from file '%s'", filePath) + var inputHeader []string for idx, row := range inFile { log.Debug().Msgf("Processing row '%d'", idx) originalMap = append(originalMap, row) if idx == 0 { // skip header row + inputHeader = row log.Debug().Msgf("Skipping header row") continue } @@ -411,7 +413,7 @@ If you do not wish to include credentials in your CSV file they can be provided log.Info().Msgf("Writing results to file '%s'", outPath) //writeCsvFile(outPath, originalMap) - mapToCSV(inputMap, outPath) + mapToCSV(inputMap, outPath, inputHeader) log.Info().Int("totalRows", totalRows). Int("totalSuccesses", totalSuccess). Int("errorCount", errorCount). From 63634b541c1f873621ec2e720d92df0dbc890e95 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 14 May 2025 12:08:32 -0700 Subject: [PATCH 15/24] fix(cli): `stores rot` re-enabled and logging updated. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/rot.go | 3355 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 1952 insertions(+), 1403 deletions(-) diff --git a/cmd/rot.go b/cmd/rot.go index 2a7478c..b8803cb 100644 --- a/cmd/rot.go +++ b/cmd/rot.go @@ -14,1406 +14,1955 @@ package cmd -//import ( -// "bufio" -// "encoding/csv" -// "encoding/json" -// "errors" -// "fmt" -// "log" -// "os" -// "strconv" -// "strings" -// -// "github.com/Keyfactor/keyfactor-go-client/v3/api" -// "github.com/spf13/cobra" -//) -// -//type templateType string -//type StoreCSVEntry struct { -// ID string `json:"id"` -// Type string `json:"type"` -// Machine string `json:"address"` -// Path string `json:"path"` -// Thumbprints map[string]bool `json:"thumbprints,omitempty"` -// Serials map[string]bool `json:"serials,omitempty"` -// Ids map[int]bool `json:"ids,omitempty"` -//} -//type ROTCert struct { -// ID int `json:"id,omitempty"` -// ThumbPrint string `json:"thumbprint,omitempty"` -// CN string `json:"cn,omitempty"` -// Locations []api.CertificateLocations `json:"locations,omitempty"` -//} -//type ROTAction struct { -// StoreID string `json:"store_id,omitempty"` -// StoreType string `json:"store_type,omitempty"` -// StorePath string `json:"store_path,omitempty"` -// Thumbprint string `json:"thumbprint,omitempty"` -// CertID int `json:"cert_id,omitempty" mapstructure:"CertID,omitempty"` -// AddCert bool `json:"add,omitempty" mapstructure:"AddCert,omitempty"` -// RemoveCert bool `json:"remove,omitempty" mapstructure:"RemoveCert,omitempty"` -//} -// -//const ( -// tTypeCerts templateType = "certs" -// reconcileDefaultFileName string = "rot_audit.csv" -//) -// -//var ( -// AuditHeader = []string{ -// "Thumbprint", -// "CertID", -// "SubjectName", -// "Issuer", -// "StoreID", -// "StoreType", -// "Machine", -// "Path", -// "AddCert", -// "RemoveCert", -// "Deployed", -// "AuditDate", -// } -// ReconciledAuditHeader = []string{ -// "Thumbprint", -// "CertID", -// "SubjectName", -// "Issuer", -// "StoreID", -// "StoreType", -// "Machine", -// "Path", -// "AddCert", -// "RemoveCert", -// "Deployed", -// "ReconciledDate", -// } -// StoreHeader = []string{ -// "StoreID", -// "StoreType", -// "StoreMachine", -// "StorePath", -// "ContainerId", -// "ContainerName", -// "LastQueriedDate", -// } -// CertHeader = []string{"Thumbprint", "SubjectName", "Issuer", "CertID", "Locations", "LastQueriedDate"} -//) -// -//// String is used both by fmt.Print and by Cobra in help text -//func (e *templateType) String() string { -// return string(*e) -//} -// -//// Set must have pointer receiver, so it doesn't change the value of a copy -//func (e *templateType) Set(v string) error { -// switch v { -// case "certs", "stores", "actions": -// *e = templateType(v) -// return nil -// default: -// return errors.New(`must be one of "certs", "stores", or "actions"`) -// } -//} -// -//// Type is only used in help text -//func (e *templateType) Type() string { -// return "string" -//} -// -//func templateTypeCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { -// return []string{ -// "certs\tGenerates template CSV for certificate input to be used w/ `--add-certs` or `--remove-certs`", -// "stores\tGenerates template CSV for certificate input to be used w/ `--stores`", -// "actions\tGenerates template CSV for certificate input to be used w/ `--actions`", -// }, cobra.ShellCompDirectiveDefault -//} -// -//func generateAuditReport( -// addCerts map[string]string, -// removeCerts map[string]string, -// stores map[string]StoreCSVEntry, -// outpath string, -// kfClient *api.Client, -//) ([][]string, map[string][]ROTAction, error) { -// log.Println("[DEBUG] generateAuditReport called") -// var ( -// data [][]string -// ) -// -// data = append(data, AuditHeader) -// var csvFile *os.File -// var fErr error -// if outpath == "" { -// csvFile, fErr = os.Create(reconcileDefaultFileName) -// outpath = reconcileDefaultFileName -// } else { -// csvFile, fErr = os.Create(outpath) -// } -// -// if fErr != nil { -// fmt.Printf("%s", fErr) -// log.Fatalf("[ERROR] creating audit file: %s", fErr) -// } -// csvWriter := csv.NewWriter(csvFile) -// cErr := csvWriter.Write(AuditHeader) -// if cErr != nil { -// fmt.Printf("%s", cErr) -// log.Fatalf("[ERROR] writing audit header: %s", cErr) -// } -// actions := make(map[string][]ROTAction) -// -// for _, cert := range addCerts { -// certLookupReq := api.GetCertificateContextArgs{ -// IncludeMetadata: boolToPointer(true), -// IncludeLocations: boolToPointer(true), -// CollectionId: nil, -// Thumbprint: cert, -// Id: 0, -// } -// certLookup, err := kfClient.GetCertificateContext(&certLookupReq) -// if err != nil { -// fmt.Printf("[ERROR] looking up certificate %s: %s\n", cert, err) -// log.Printf("[ERROR] looking up cert: %s\n%v", cert, err) -// continue -// } -// certID := certLookup.Id -// certIDStr := strconv.Itoa(certID) -// for _, store := range stores { -// if _, ok := store.Thumbprints[cert]; ok { -// // Cert is already in the store do nothing -// row := []string{ -// cert, -// certIDStr, -// certLookup.IssuedDN, -// certLookup.IssuerDN, -// store.ID, -// store.Type, -// store.Machine, -// store.Path, -// "false", -// "false", -// "true", -// getCurrentTime(""), -// } -// data = append(data, row) -// wErr := csvWriter.Write(row) -// if wErr != nil { -// fmt.Printf("[ERROR] writing audit file row: %s\n", wErr) -// log.Printf("[ERROR] writing audit row: %s", wErr) -// } -// } else { -// // Cert is not deployed to this store and will need to be added -// row := []string{ -// cert, -// certIDStr, -// certLookup.IssuedDN, -// certLookup.IssuerDN, -// store.ID, -// store.Type, -// store.Machine, -// store.Path, -// "true", -// "false", -// "false", -// getCurrentTime(""), -// } -// data = append(data, row) -// wErr := csvWriter.Write(row) -// if wErr != nil { -// fmt.Printf("[ERROR] writing audit file row: %s\n", wErr) -// log.Printf("[ERROR] writing audit row: %s", wErr) -// } -// actions[cert] = append( -// actions[cert], ROTAction{ -// Thumbprint: cert, -// CertID: certID, -// StoreID: store.ID, -// StoreType: store.Type, -// StorePath: store.Path, -// AddCert: true, -// RemoveCert: false, -// }, -// ) -// } -// } -// } -// for _, cert := range removeCerts { -// certLookupReq := api.GetCertificateContextArgs{ -// IncludeMetadata: boolToPointer(true), -// IncludeLocations: boolToPointer(true), -// CollectionId: nil, -// Thumbprint: cert, -// Id: 0, -// } -// certLookup, err := kfClient.GetCertificateContext(&certLookupReq) -// if err != nil { -// log.Printf("[ERROR] looking up cert: %s", err) -// continue -// } -// certID := certLookup.Id -// certIDStr := strconv.Itoa(certID) -// for _, store := range stores { -// if _, ok := store.Thumbprints[cert]; ok { -// // Cert is deployed to this store and will need to be removed -// row := []string{ -// cert, -// certIDStr, -// certLookup.IssuedDN, -// certLookup.IssuerDN, -// store.ID, -// store.Type, -// store.Machine, -// store.Path, -// "false", -// "true", -// "true", -// getCurrentTime(""), -// } -// data = append(data, row) -// wErr := csvWriter.Write(row) -// if wErr != nil { -// fmt.Printf("%s", wErr) -// log.Printf("[ERROR] writing row to CSV: %s", wErr) -// } -// actions[cert] = append( -// actions[cert], ROTAction{ -// Thumbprint: cert, -// CertID: certID, -// StoreID: store.ID, -// StoreType: store.Type, -// StorePath: store.Path, -// AddCert: false, -// RemoveCert: true, -// }, -// ) -// } else { -// // Cert is not deployed to this store do nothing -// row := []string{ -// cert, -// certIDStr, -// certLookup.IssuedDN, -// certLookup.IssuerDN, -// store.ID, -// store.Type, -// store.Machine, -// store.Path, -// "false", -// "false", -// "false", -// getCurrentTime(""), -// } -// data = append(data, row) -// wErr := csvWriter.Write(row) -// if wErr != nil { -// fmt.Printf("%s", wErr) -// log.Printf("[ERROR] writing row to CSV: %s", wErr) -// } -// } -// } -// } -// csvWriter.Flush() -// ioErr := csvFile.Close() -// if ioErr != nil { -// fmt.Println(ioErr) -// log.Printf("[ERROR] closing audit file: %s", ioErr) -// } -// fmt.Printf("Audit report written to %s\n", outpath) -// return data, actions, nil -//} -// -//func reconcileRoots(actions map[string][]ROTAction, kfClient *api.Client, reportFile string, dryRun bool) error { -// log.Printf("[DEBUG] Reconciling roots") -// if len(actions) == 0 { -// log.Printf("[INFO] No actions to take, roots are up-to-date.") -// return nil -// } -// rFileName := fmt.Sprintf("%s_reconciled.csv", strings.Split(reportFile, ".csv")[0]) -// csvFile, fErr := os.Create(rFileName) -// if fErr != nil { -// fmt.Printf("[ERROR] creating reconciled report file: %s", fErr) -// } -// csvWriter := csv.NewWriter(csvFile) -// cErr := csvWriter.Write(ReconciledAuditHeader) -// if cErr != nil { -// fmt.Printf("%s", cErr) -// log.Fatalf("[ERROR] writing audit header: %s", cErr) -// } -// for thumbprint, action := range actions { -// -// for _, a := range action { -// if a.AddCert { -// log.Printf("[INFO] Adding cert %s to store %s(%s)", thumbprint, a.StoreID, a.StorePath) -// if !dryRun { -// cStore := api.CertificateStore{ -// CertificateStoreId: a.StoreID, -// Overwrite: true, -// } -// var stores []api.CertificateStore -// stores = append(stores, cStore) -// schedule := &api.InventorySchedule{ -// Immediate: boolToPointer(true), -// } -// addReq := api.AddCertificateToStore{ -// CertificateId: a.CertID, -// CertificateStores: &stores, -// InventorySchedule: schedule, -// } -// log.Printf("[DEBUG] Adding cert %s to store %s", thumbprint, a.StoreID) -// log.Printf("[TRACE] Add request: %+v", addReq) -// addReqJSON, _ := json.Marshal(addReq) -// log.Printf("[TRACE] Add request JSON: %s", addReqJSON) -// _, err := kfClient.AddCertificateToStores(&addReq) -// if err != nil { -// fmt.Printf( -// "[ERROR] adding cert %s (%d) to store %s (%s): %s\n", -// a.Thumbprint, -// a.CertID, -// a.StoreID, -// a.StorePath, -// err, -// ) -// continue -// } -// } else { -// log.Printf("[INFO] DRY RUN: Would have added cert %s from store %s", thumbprint, a.StoreID) -// } -// } else if a.RemoveCert { -// if !dryRun { -// log.Printf("[INFO] Removing cert from store %s", a.StoreID) -// cStore := api.CertificateStore{ -// CertificateStoreId: a.StoreID, -// Alias: a.Thumbprint, -// } -// var stores []api.CertificateStore -// stores = append(stores, cStore) -// schedule := &api.InventorySchedule{ -// Immediate: boolToPointer(true), -// } -// removeReq := api.RemoveCertificateFromStore{ -// CertificateId: a.CertID, -// CertificateStores: &stores, -// InventorySchedule: schedule, -// } -// _, err := kfClient.RemoveCertificateFromStores(&removeReq) -// if err != nil { -// fmt.Printf( -// "[ERROR] removing cert %s (ID: %d) from store %s (%s): %s\n", -// a.Thumbprint, -// a.CertID, -// a.StoreID, -// a.StorePath, -// err, -// ) -// } -// } else { -// fmt.Printf("DRY RUN: Would have removed cert %s from store %s\n", thumbprint, a.StoreID) -// log.Printf("[INFO] DRY RUN: Would have removed cert %s from store %s", thumbprint, a.StoreID) -// } -// } -// } -// } -// return nil -//} -// -//func readCertsFile(certsFilePath string, kfclient *api.Client) (map[string]string, error) { -// // Read in the cert CSV -// csvFile, _ := os.Open(certsFilePath) -// reader := csv.NewReader(bufio.NewReader(csvFile)) -// certEntries, _ := reader.ReadAll() -// var certs = make(map[string]string) -// for _, entry := range certEntries { -// switch entry[0] { -// case "CertID", "thumbprint", "id", "CertId", "Thumbprint": -// continue // Skip header -// } -// certs[entry[0]] = entry[0] -// } -// return certs, nil -//} -// -//func isRootStore( -// st *api.GetCertificateStoreResponse, -// invs *[]api.CertStoreInventoryV1, -// minCerts int, -// maxKeys int, -// maxLeaf int, -//) bool { -// leafCount := 0 -// keyCount := 0 -// certCount := 0 -// for _, inv := range *invs { -// log.Printf("[DEBUG] inv: %v", inv) -// certCount += len(inv.Certificates) -// -// for _, cert := range inv.Certificates { -// if cert.IssuedDN != cert.IssuerDN { -// leafCount++ -// } -// if inv.Parameters["PrivateKeyEntry"] == "Yes" { -// keyCount++ -// } -// } -// } -// if certCount < minCerts && minCerts >= 0 { -// log.Printf("[DEBUG] Store %s has %d certs, less than the required count of %d", st.Id, certCount, minCerts) -// return false -// } -// if leafCount > maxLeaf && maxLeaf >= 0 { -// log.Printf("[DEBUG] Store %s has too many leaf certs", st.Id) -// return false -// } -// -// if keyCount > maxKeys && maxKeys >= 0 { -// log.Printf("[DEBUG] Store %s has too many keys", st.Id) -// return false -// } -// -// return true -//} -// -//var ( -// rotCmd = &cobra.Command{ -// Use: "rot", -// Short: "Root of trust utility", -// Long: `Root of trust allows you to manage your trusted roots using Keyfactor certificate stores. -//For example if you wish to add a list of "root" certs to a list of certificate stores you would simply generate and fill -//out the template CSV file. These template files can be generated with the following commands: -//kfutil stores rot generate-template --type certs -//kfutil stores rot generate-template --type stores -//Once those files are filled out you can use the following command to add the certs to the stores: -//kfutil stores rot audit --certs-file --stores-file -//Will generate a CSV report file 'rot_audit.csv' of what actions will be taken. If those actions are correct you can run -//the following command to actually perform the actions: -//kfutil stores rot reconcile --certs-file --stores-file -//OR if you want to use the audit report file generated you can run this command: -//kfutil stores rot reconcile --import-csv -//`, -// } -// rotAuditCmd = &cobra.Command{ -// Use: "audit", -// Aliases: nil, -// SuggestFor: nil, -// Short: "Audit generates a CSV report of what actions will be taken based on input CSV files.", -// Long: `Root of Trust Audit: Will read and parse inputs to generate a report of certs that need to be added or removed from the "root of trust" stores.`, -// Example: "", -// ValidArgs: nil, -// ValidArgsFunction: nil, -// Args: nil, -// ArgAliases: nil, -// BashCompletionFunction: "", -// Deprecated: "", -// Annotations: nil, -// Version: "", -// PersistentPreRun: nil, -// PersistentPreRunE: nil, -// PreRun: nil, -// PreRunE: nil, -// Run: func(cmd *cobra.Command, args []string) { -// // Global flags -// debugFlag, _ := cmd.Flags().GetBool("debugFlag") -// configFile, _ := cmd.Flags().GetString("config") -// noPrompt, _ := cmd.Flags().GetBool("no-prompt") -// profile, _ := cmd.Flags().GetString("profile") -// -// kfcUsername, _ := cmd.Flags().GetString("kfcUsername") -// kfcPassword, _ := cmd.Flags().GetString("kfcPassword") -// kfcDomain, _ := cmd.Flags().GetString("kfcDomain") -// -// -// -// debugModeEnabled := checkDebug(debugFlag) -// log.Println("Debug mode enabled: ", debugModeEnabled) -// var lookupFailures []string -// kfClient, _ := initClient(false) -// storesFile, _ := cmd.Flags().GetString("stores") -// addRootsFile, _ := cmd.Flags().GetString("add-certs") -// removeRootsFile, _ := cmd.Flags().GetString("remove-certs") -// minCerts, _ := cmd.Flags().GetInt("min-certs") -// maxLeaves, _ := cmd.Flags().GetInt("max-leaf-certs") -// maxKeys, _ := cmd.Flags().GetInt("max-keys") -// dryRun, _ := cmd.Flags().GetBool("dry-run") -// outpath, _ := cmd.Flags().GetString("outpath") -// // Read in the stores CSV -// log.Printf("[DEBUG] storesFile: %s", storesFile) -// log.Printf("[DEBUG] addRootsFile: %s", addRootsFile) -// log.Printf("[DEBUG] removeRootsFile: %s", removeRootsFile) -// log.Printf("[DEBUG] dryRun: %t", dryRun) -// // Read in the stores CSV -// csvFile, _ := os.Open(storesFile) -// reader := csv.NewReader(bufio.NewReader(csvFile)) -// storeEntries, _ := reader.ReadAll() -// var stores = make(map[string]StoreCSVEntry) -// validHeader := false -// for _, entry := range storeEntries { -// if strings.EqualFold(strings.Join(entry, ","), strings.Join(StoreHeader, ",")) { -// validHeader = true -// continue // Skip header -// } -// if !validHeader { -// fmt.Printf("[ERROR] Invalid header in stores file. Expected: %s", strings.Join(StoreHeader, ",")) -// log.Fatalf("[ERROR] Stores CSV file is missing a valid header") -// } -// apiResp, err := kfClient.GetCertificateStoreByID(entry[0]) -// if err != nil { -// log.Printf("[ERROR] getting cert store: %s", err) -// _ = append(lookupFailures, strings.Join(entry, ",")) -// continue -// } -// -// //inventory, invErr := kfClient.GetCertStoreInventoryV1(entry[0]) -// //if invErr != nil { -// // log.Printf("[ERROR] getting cert store inventory for: %s\n%s", entry[0], invErr) -// //} -// var inventory []api.CertStoreInventoryV1 //TODO: Update this to use SDK inventory -// -// if !isRootStore(apiResp, &inventory, minCerts, maxLeaves, maxKeys) { -// fmt.Printf("Store %s is not a root store, skipping.\n", entry[0]) -// log.Printf("[WARN] Store %s is not a root store", apiResp.Id) -// continue -// } else { -// log.Printf("[INFO] Store %s is a root store", apiResp.Id) -// } -// -// stores[entry[0]] = StoreCSVEntry{ -// ID: entry[0], -// Type: entry[1], -// Machine: entry[2], -// Path: entry[3], -// Thumbprints: make(map[string]bool), -// Serials: make(map[string]bool), -// Ids: make(map[int]bool), -// } -// for _, cert := range inventory { -// thumb := cert.Thumbprints -// for t, v := range thumb { -// stores[entry[0]].Thumbprints[t] = v -// } -// for t, v := range cert.Serials { -// stores[entry[0]].Serials[t] = v -// } -// for t, v := range cert.Ids { -// stores[entry[0]].Ids[t] = v -// } -// } -// -// } -// -// // Read in the add addCerts CSV -// var certsToAdd = make(map[string]string) -// if addRootsFile != "" { -// var rcfErr error -// certsToAdd, rcfErr = readCertsFile(addRootsFile, kfClient) -// if rcfErr != nil { -// fmt.Printf("[ERROR] reading certs file %s: %s", addRootsFile, rcfErr) -// log.Fatalf("[ERROR] reading addCerts file: %s", rcfErr) -// } -// addCertsJSON, _ := json.Marshal(certsToAdd) -// log.Printf("[DEBUG] add certs JSON: %s", string(addCertsJSON)) -// log.Println("[DEBUG] AddCert ROT called") -// } else { -// log.Printf("[DEBUG] No addCerts file specified") -// log.Printf("[DEBUG] No addCerts = %s", certsToAdd) -// } -// -// // Read in the remove removeCerts CSV -// var certsToRemove = make(map[string]string) -// if removeRootsFile != "" { -// var rcfErr error -// certsToRemove, rcfErr = readCertsFile(removeRootsFile, kfClient) -// if rcfErr != nil { -// fmt.Printf("[ERROR] reading removeCerts file %s: %s", removeRootsFile, rcfErr) -// log.Fatalf("[ERROR] reading removeCerts file: %s", rcfErr) -// } -// removeCertsJSON, _ := json.Marshal(certsToRemove) -// log.Printf("[DEBUG] remove certs JSON: %s", string(removeCertsJSON)) -// } else { -// log.Printf("[DEBUG] No removeCerts file specified") -// log.Printf("[DEBUG] No removeCerts = %s", certsToRemove) -// } -// _, _, gErr := generateAuditReport(certsToAdd, certsToRemove, stores, outpath, kfClient) -// if gErr != nil { -// log.Fatalf("[ERROR] generating audit report: %s", gErr) -// } -// }, -// RunE: nil, -// PostRun: nil, -// PostRunE: nil, -// PersistentPostRun: nil, -// PersistentPostRunE: nil, -// FParseErrWhitelist: cobra.FParseErrWhitelist{}, -// CompletionOptions: cobra.CompletionOptions{}, -// TraverseChildren: false, -// Hidden: false, -// SilenceErrors: false, -// SilenceUsage: false, -// DisableFlagParsing: false, -// DisableAutoGenTag: false, -// DisableFlagsInUseLine: false, -// DisableSuggestions: false, -// SuggestionsMinimumDistance: 0, -// } -// rotReconcileCmd = &cobra.Command{ -// Use: "reconcile", -// Aliases: nil, -// SuggestFor: nil, -// Short: "Reconcile either takes in or will generate an audit report and then add/remove certs as needed.", -// Long: `Root of Trust (rot): Will parse either a combination of CSV files that define certs to -//add and/or certs to remove with a CSV of certificate stores or an audit CSV file. If an audit CSV file is provided, the -//add and remove actions defined in the audit file will be immediately executed. If a combination of CSV files are provided, -//the utility will first generate an audit report and then execute the add/remove actions defined in the audit report.`, -// Example: "", -// ValidArgs: nil, -// ValidArgsFunction: nil, -// Args: nil, -// ArgAliases: nil, -// BashCompletionFunction: "", -// Deprecated: "", -// Annotations: nil, -// Version: "", -// PersistentPreRun: nil, -// PersistentPreRunE: nil, -// PreRun: nil, -// PreRunE: nil, -// Run: func(cmd *cobra.Command, args []string) { -// // Global flags -// debugFlag, _ := cmd.Flags().GetBool("debugFlag") -// configFile, _ := cmd.Flags().GetString("config") -// noPrompt, _ := cmd.Flags().GetBool("no-prompt") -// profile, _ := cmd.Flags().GetString("profile") -// -// kfcUsername, _ := cmd.Flags().GetString("kfcUsername") -// kfcPassword, _ := cmd.Flags().GetString("kfcPassword") -// kfcDomain, _ := cmd.Flags().GetString("kfcDomain") -// -// -// -// debugModeEnabled := checkDebug(debugFlag) -// -// log.Println("Debug mode enabled: ", debugModeEnabled) -// -// var lookupFailures []string -// kfClient, _ := initClient(false) -// storesFile, _ := cmd.Flags().GetString("stores") -// addRootsFile, _ := cmd.Flags().GetString("add-certs") -// isCSV, _ := cmd.Flags().GetBool("import-csv") -// reportFile, _ := cmd.Flags().GetString("input-file") -// removeRootsFile, _ := cmd.Flags().GetString("remove-certs") -// minCerts, _ := cmd.Flags().GetInt("min-certs") -// maxLeaves, _ := cmd.Flags().GetInt("max-leaf-certs") -// maxKeys, _ := cmd.Flags().GetInt("max-keys") -// dryRun, _ := cmd.Flags().GetBool("dry-run") -// outpath, _ := cmd.Flags().GetString("outpath") -// -// log.Printf("[DEBUG] configFile: %s", configFile) -// log.Printf("[DEBUG] storesFile: %s", storesFile) -// log.Printf("[DEBUG] addRootsFile: %s", addRootsFile) -// log.Printf("[DEBUG] removeRootsFile: %s", removeRootsFile) -// log.Printf("[DEBUG] dryRun: %t", dryRun) -// -// // Parse existing audit report -// if isCSV && reportFile != "" { -// log.Printf("[DEBUG] isCSV: %t", isCSV) -// log.Printf("[DEBUG] reportFile: %s", reportFile) -// // Read in the CSV -// csvFile, err := os.Open(reportFile) -// if err != nil { -// fmt.Printf("[ERROR] opening file: %s", err) -// log.Fatalf("[ERROR] opening CSV file: %s", err) -// } -// validHeader := false -// -// aCSV := csv.NewReader(csvFile) -// aCSV.FieldsPerRecord = -1 -// inFile, cErr := aCSV.ReadAll() -// if cErr != nil { -// fmt.Printf("[ERROR] reading CSV file: %s", cErr) -// log.Fatalf("[ERROR] reading CSV file: %s", cErr) -// } -// actions := make(map[string][]ROTAction) -// fieldMap := make(map[int]string) -// for i, field := range AuditHeader { -// fieldMap[i] = field -// } -// for ri, row := range inFile { -// if strings.EqualFold(strings.Join(row, ","), strings.Join(AuditHeader, ",")) { -// validHeader = true -// continue // Skip header -// } -// if !validHeader { -// fmt.Printf( -// "[ERROR] Invalid header in stores file. Expected: %s", -// strings.Join(AuditHeader, ","), -// ) -// log.Fatalf("[ERROR] Stores CSV file is missing a valid header") -// } -// action := make(map[string]interface{}) -// -// for i, field := range row { -// fieldInt, iErr := strconv.Atoi(field) -// if iErr != nil { -// log.Printf("[DEBUG] Field %s is not an int", field) -// action[fieldMap[i]] = field -// } else { -// action[fieldMap[i]] = fieldInt -// } -// -// } -// -// addCertStr, aOk := action["AddCert"].(string) -// if !aOk { -// addCertStr = "" -// } -// addCert, acErr := strconv.ParseBool(addCertStr) -// if acErr != nil { -// addCert = false -// } -// -// removeCertStr, rOk := action["RemoveCert"].(string) -// if !rOk { -// removeCertStr = "" -// } -// removeCert, rcErr := strconv.ParseBool(removeCertStr) -// if rcErr != nil { -// removeCert = false -// } -// -// sType, sOk := action["StoreType"].(string) -// if !sOk { -// sType = "" -// } -// -// sPath, pOk := action["Path"].(string) -// if !pOk { -// sPath = "" -// } -// -// tp, tpOk := action["Thumbprint"].(string) -// if !tpOk { -// tp = "" -// } -// cid, cidOk := action["CertID"].(int) -// if !cidOk { -// cid = -1 -// } -// -// if !tpOk && !cidOk { -// fmt.Printf("[ERROR] Missing Thumbprint or CertID for row %d in report file %s", ri, reportFile) -// log.Printf("[ERROR] Invalid action: %v", action) -// continue -// } -// -// sId, sIdOk := action["StoreID"].(string) -// if !sIdOk { -// fmt.Printf("[ERROR] Missing StoreID for row %d in report file %s", ri, reportFile) -// log.Printf("[ERROR] Invalid action: %v", action) -// continue -// } -// if cid == -1 && tp != "" { -// certLookupReq := api.GetCertificateContextArgs{ -// IncludeMetadata: boolToPointer(true), -// IncludeLocations: boolToPointer(true), -// CollectionId: nil, -// Thumbprint: tp, -// Id: 0, -// } -// certLookup, err := kfClient.GetCertificateContext(&certLookupReq) -// if err != nil { -// fmt.Printf("[ERROR] looking up certificate %s: %s\n", tp, err) -// log.Printf("[ERROR] looking up cert: %s\n%v", tp, err) -// continue -// } -// cid = certLookup.Id -// } -// -// a := ROTAction{ -// StoreID: sId, -// StoreType: sType, -// StorePath: sPath, -// Thumbprint: tp, -// CertID: cid, -// AddCert: addCert, -// RemoveCert: removeCert, -// } -// -// actions[a.Thumbprint] = append(actions[a.Thumbprint], a) -// } -// if len(actions) == 0 { -// fmt.Println("No reconciliation actions to take, root stores are up-to-date. Exiting.") -// return -// } -// rErr := reconcileRoots(actions, kfClient, reportFile, dryRun) -// if rErr != nil { -// fmt.Printf("[ERROR] reconciling roots: %s", rErr) -// log.Fatalf("[ERROR] reconciling roots: %s", rErr) -// } -// defer csvFile.Close() -// -// orchsURL := fmt.Sprintf("https://%s/Keyfactor/Portal/AgentJobStatus/Index", kfClient.Hostname) -// -// fmt.Println(fmt.Sprintf("Reconciliation completed. Check orchestrator jobs for details. %s", orchsURL)) -// } else { -// // Read in the stores CSV -// csvFile, _ := os.Open(storesFile) -// reader := csv.NewReader(bufio.NewReader(csvFile)) -// storeEntries, _ := reader.ReadAll() -// var stores = make(map[string]StoreCSVEntry) -// for i, entry := range storeEntries { -// if entry[0] == "StoreID" || entry[0] == "StoreId" || i == 0 { -// continue // Skip header -// } -// apiResp, err := kfClient.GetCertificateStoreByID(entry[0]) -// if err != nil { -// log.Printf("[ERROR] getting cert store: %s", err) -// lookupFailures = append(lookupFailures, entry[0]) -// continue -// } -// inventory, invErr := kfClient.GetCertStoreInventoryV1(entry[0]) -// if invErr != nil { -// log.Fatalf("[ERROR] getting cert store inventory: %s", invErr) -// } -// -// if !isRootStore(apiResp, inventory, minCerts, maxLeaves, maxKeys) { -// log.Printf("[WARN] Store %s is not a root store", apiResp.Id) -// continue -// } else { -// log.Printf("[INFO] Store %s is a root store", apiResp.Id) -// } -// -// stores[entry[0]] = StoreCSVEntry{ -// ID: entry[0], -// Type: entry[1], -// Machine: entry[2], -// Path: entry[3], -// Thumbprints: make(map[string]bool), -// Serials: make(map[string]bool), -// Ids: make(map[int]bool), -// } -// for _, cert := range *inventory { -// thumb := cert.Thumbprints -// for t, v := range thumb { -// stores[entry[0]].Thumbprints[t] = v -// } -// for t, v := range cert.Serials { -// stores[entry[0]].Serials[t] = v -// } -// for t, v := range cert.Ids { -// stores[entry[0]].Ids[t] = v -// } -// } -// -// } -// if len(lookupFailures) > 0 { -// fmt.Printf("[ERROR] the following stores were not found: %s", strings.Join(lookupFailures, ",")) -// log.Fatalf("[ERROR] the following stores were not found: %s", strings.Join(lookupFailures, ",")) -// } -// if len(stores) == 0 { -// fmt.Println("[ERROR] no root stores found. Exiting.") -// log.Fatalf("[ERROR] No root stores found. Exiting.") -// } -// // Read in the add addCerts CSV -// var certsToAdd = make(map[string]string) -// if addRootsFile != "" { -// certsToAdd, _ = readCertsFile(addRootsFile, kfClient) -// log.Printf("[DEBUG] ROT add certs called") -// } else { -// log.Printf("[INFO] No addCerts file specified") -// } -// -// // Read in the remove removeCerts CSV -// var certsToRemove = make(map[string]string) -// if removeRootsFile != "" { -// certsToRemove, _ = readCertsFile(removeRootsFile, kfClient) -// log.Printf("[DEBUG] ROT remove certs called") -// } else { -// log.Printf("[DEBUG] No removeCerts file specified") -// } -// _, actions, err := generateAuditReport(certsToAdd, certsToRemove, stores, outpath, kfClient) -// if err != nil { -// log.Fatalf("[ERROR] generating audit report: %s", err) -// } -// if len(actions) == 0 { -// fmt.Println("No reconciliation actions to take, root stores are up-to-date. Exiting.") -// return -// } -// rErr := reconcileRoots(actions, kfClient, reportFile, dryRun) -// if rErr != nil { -// fmt.Printf("[ERROR] reconciling roots: %s", rErr) -// log.Fatalf("[ERROR] reconciling roots: %s", rErr) -// } -// if lookupFailures != nil { -// fmt.Printf("The following stores could not be found: %s", strings.Join(lookupFailures, ",")) -// } -// orchsURL := fmt.Sprintf("https://%s/Keyfactor/Portal/AgentJobStatus/Index", kfClient.Hostname) -// -// fmt.Println(fmt.Sprintf("Reconciliation completed. Check orchestrator jobs for details. %s", orchsURL)) -// } -// -// }, -// RunE: nil, -// PostRun: nil, -// PostRunE: nil, -// PersistentPostRun: nil, -// PersistentPostRunE: nil, -// FParseErrWhitelist: cobra.FParseErrWhitelist{}, -// CompletionOptions: cobra.CompletionOptions{}, -// TraverseChildren: false, -// Hidden: false, -// SilenceErrors: false, -// SilenceUsage: false, -// DisableFlagParsing: false, -// DisableAutoGenTag: false, -// DisableFlagsInUseLine: false, -// DisableSuggestions: false, -// SuggestionsMinimumDistance: 0, -// } -// rotGenStoreTemplateCmd = &cobra.Command{ -// Use: "generate-template", -// Aliases: nil, -// SuggestFor: nil, -// Short: "For generating Root Of Trust template(s)", -// Long: `Root Of Trust: Will parse a CSV and attempt to deploy a cert or set of certs into a list of cert stores.`, -// Example: "", -// ValidArgs: nil, -// ValidArgsFunction: nil, -// Args: nil, -// ArgAliases: nil, -// BashCompletionFunction: "", -// Deprecated: "", -// Annotations: nil, -// Version: "", -// PersistentPreRun: nil, -// PersistentPreRunE: nil, -// PreRun: nil, -// PreRunE: nil, -// Run: func(cmd *cobra.Command, args []string) { -// // Global flags -// debugFlag, _ := cmd.Flags().GetBool("debugFlag") -// configFile, _ := cmd.Flags().GetString("config") -// noPrompt, _ := cmd.Flags().GetBool("no-prompt") -// profile, _ := cmd.Flags().GetString("profile") -// -// kfcUsername, _ := cmd.Flags().GetString("kfcUsername") -// kfcPassword, _ := cmd.Flags().GetString("kfcPassword") -// kfcDomain, _ := cmd.Flags().GetString("kfcDomain") -// -// -// -// debugModeEnabled := checkDebug(debugFlag) -// log.Println("Debug mode enabled: ", debugModeEnabled) -// -// templateType, _ := cmd.Flags().GetString("type") -// format, _ := cmd.Flags().GetString("format") -// outPath, _ := cmd.Flags().GetString("outpath") -// storeType, _ := cmd.Flags().GetStringSlice("store-type") -// containerName, _ := cmd.Flags().GetStringSlice("container-name") -// collection, _ := cmd.Flags().GetStringSlice("collection") -// subjectName, _ := cmd.Flags().GetStringSlice("cn") -// stID := -1 -// var storeData []api.GetCertificateStoreResponse -// var csvStoreData [][]string -// var csvCertData [][]string -// var rowLookup = make(map[string]bool) -// kfClient, cErr := initClient(false) -// if len(storeType) != 0 { -// for _, s := range storeType { -// if cErr != nil { -// log.Fatalf("[ERROR] creating client: %s", cErr) -// } -// var sType *api.CertificateStoreType -// var stErr error -// if s == "all" { -// sType = &api.CertificateStoreType{ -// Name: "", -// ShortName: "", -// Capability: "", -// StoreType: 0, -// ImportType: 0, -// LocalStore: false, -// SupportedOperations: nil, -// Properties: nil, -// EntryParameters: nil, -// PasswordOptions: nil, -// StorePathType: "", -// StorePathValue: "", -// PrivateKeyAllowed: "", -// JobProperties: nil, -// ServerRequired: false, -// PowerShell: false, -// BlueprintAllowed: false, -// CustomAliasAllowed: "", -// ServerRegistration: 0, -// InventoryEndpoint: "", -// InventoryJobType: "", -// ManagementJobType: "", -// DiscoveryJobType: "", -// EnrollmentJobType: "", -// } -// } else { -// // check if s is an int -// sInt, err := strconv.Atoi(s) -// if err == nil { -// sType, stErr = kfClient.GetCertificateStoreTypeById(sInt) -// } else { -// sType, stErr = kfClient.GetCertificateStoreTypeByName(s) -// } -// if stErr != nil { -// fmt.Printf("[ERROR] getting store type '%s'. %s\n", s, stErr) -// continue -// } -// stID = sType.StoreType // This is the template type ID -// } -// -// if stID >= 0 || s == "all" { -// log.Printf("[DEBUG] Store type ID: %d\n", stID) -// params := make(map[string]interface{}) -// stores, sErr := kfClient.ListCertificateStores(¶ms) -// if sErr != nil { -// fmt.Printf("[ERROR] getting certificate stores of type '%s': %s\n", s, sErr) -// log.Fatalf("[ERROR] getting certificate stores of type '%s': %s", s, sErr) -// } -// for _, store := range *stores { -// if store.CertStoreType == stID || s == "all" { -// storeData = append(storeData, store) -// if !rowLookup[store.Id] { -// lineData := []string{ -// //"StoreID", "StoreType", "StoreMachine", "StorePath", "ContainerId" -// store.Id, -// fmt.Sprintf("%s", sType.ShortName), -// store.ClientMachine, -// store.StorePath, -// fmt.Sprintf("%d", store.ContainerId), -// store.ContainerName, -// getCurrentTime(""), -// } -// csvStoreData = append(csvStoreData, lineData) -// rowLookup[store.Id] = true -// } -// } -// } -// } -// } -// fmt.Println("Done") -// } -// if len(containerName) != 0 { -// for _, c := range containerName { -// -// if cErr != nil { -// log.Fatalf("[ERROR] creating client: %s", cErr) -// } -// cStoresResp, scErr := kfClient.GetCertificateStoreByContainerID(c) -// if scErr != nil { -// fmt.Printf("[ERROR] getting store container: %s\n", scErr) -// } -// if cStoresResp != nil { -// for _, store := range *cStoresResp { -// sType, stErr := kfClient.GetCertificateStoreType(store.CertStoreType) -// if stErr != nil { -// fmt.Printf("[ERROR] getting store type: %s\n", stErr) -// continue -// } -// storeData = append(storeData, store) -// if !rowLookup[store.Id] { -// lineData := []string{ -// // "StoreID", "StoreType", "StoreMachine", "StorePath", "ContainerId" -// store.Id, -// sType.ShortName, -// store.ClientMachine, -// store.StorePath, -// fmt.Sprintf("%d", store.ContainerId), -// store.ContainerName, -// getCurrentTime(""), -// } -// csvStoreData = append(csvStoreData, lineData) -// rowLookup[store.Id] = true -// } -// } -// -// } -// } -// } -// if len(collection) != 0 { -// for _, c := range collection { -// if cErr != nil { -// fmt.Println("[ERROR] connecting to Keyfactor. Please check your configuration and try again.") -// log.Fatalf("[ERROR] creating client: %s", cErr) -// } -// q := make(map[string]string) -// q["collection"] = c -// certsResp, scErr := kfClient.ListCertificates(q) -// if scErr != nil { -// fmt.Printf("No certificates found in collection: %s\n", scErr) -// } -// if certsResp != nil { -// for _, cert := range certsResp { -// if !rowLookup[cert.Thumbprint] { -// lineData := []string{ -// // "Thumbprint", "SubjectName", "Issuer", "CertID", "Locations", "LastQueriedDate" -// cert.Thumbprint, -// cert.IssuedCN, -// cert.IssuerDN, -// fmt.Sprintf("%d", cert.Id), -// fmt.Sprintf("%v", cert.Locations), -// getCurrentTime(""), -// } -// csvCertData = append(csvCertData, lineData) -// rowLookup[cert.Thumbprint] = true -// } -// } -// -// } -// } -// } -// if len(subjectName) != 0 { -// for _, s := range subjectName { -// if cErr != nil { -// fmt.Println("[ERROR] connecting to Keyfactor. Please check your configuration and try again.") -// log.Fatalf("[ERROR] creating client: %s", cErr) -// } -// q := make(map[string]string) -// q["subject"] = s -// certsResp, scErr := kfClient.ListCertificates(q) -// if scErr != nil { -// fmt.Printf("No certificates found with CN: %s\n", scErr) -// } -// if certsResp != nil { -// for _, cert := range certsResp { -// if !rowLookup[cert.Thumbprint] { -// locationsFormatted := "" -// for _, loc := range cert.Locations { -// locationsFormatted += fmt.Sprintf("%s:%s\n", loc.StoreMachine, loc.StorePath) -// } -// lineData := []string{ -// // "Thumbprint", "SubjectName", "Issuer", "CertID", "Locations", "LastQueriedDate" -// cert.Thumbprint, -// cert.IssuedCN, -// cert.IssuerDN, -// fmt.Sprintf("%d", cert.Id), -// locationsFormatted, -// getCurrentTime(""), -// } -// csvCertData = append(csvCertData, lineData) -// rowLookup[cert.Thumbprint] = true -// } -// } -// -// } -// } -// } -// // Create CSV template file -// -// var filePath string -// if outPath != "" { -// filePath = outPath -// } else { -// filePath = fmt.Sprintf("%s_template.%s", templateType, format) -// } -// file, err := os.Create(filePath) -// if err != nil { -// fmt.Printf("[ERROR] creating file: %s", err) -// log.Fatal("Cannot create file", err) -// } -// -// switch format { -// case "csv": -// writer := csv.NewWriter(file) -// var data [][]string -// switch templateType { -// case "stores": -// data = append(data, StoreHeader) -// if len(csvStoreData) != 0 { -// data = append(data, csvStoreData...) -// } -// case "certs": -// data = append(data, CertHeader) -// if len(csvCertData) != 0 { -// data = append(data, csvCertData...) -// } -// case "actions": -// data = append(data, AuditHeader) -// } -// csvErr := writer.WriteAll(data) -// if csvErr != nil { -// fmt.Println(csvErr) -// } -// defer file.Close() -// -// case "json": -// writer := bufio.NewWriter(file) -// _, err := writer.WriteString("StoreID,StoreType,StoreMachine,StorePath") -// if err != nil { -// log.Fatal("Cannot write to file", err) -// } -// } -// fmt.Printf("Template file created at %s.\n", filePath) -// }, -// RunE: nil, -// PostRun: nil, -// PostRunE: nil, -// PersistentPostRun: nil, -// PersistentPostRunE: nil, -// FParseErrWhitelist: cobra.FParseErrWhitelist{}, -// CompletionOptions: cobra.CompletionOptions{}, -// TraverseChildren: false, -// Hidden: false, -// SilenceErrors: false, -// SilenceUsage: false, -// DisableFlagParsing: false, -// DisableAutoGenTag: false, -// DisableFlagsInUseLine: false, -// DisableSuggestions: false, -// SuggestionsMinimumDistance: 0, -// } -//) -// -//func init() { -// log.SetFlags(log.LstdFlags | log.Lshortfile) -// log.SetOutput(os.Stdout) -// var ( -// stores string -// addCerts string -// removeCerts string -// minCertsInStore int -// maxPrivateKeys int -// maxLeaves int -// tType = tTypeCerts -// outPath string -// outputFormat string -// inputFile string -// storeTypes []string -// containerNames []string -// collections []string -// subjectNames []string -// ) -// -// storesCmd.AddCommand(rotCmd) -// -// // Root of trust `audit` command -// rotCmd.AddCommand(rotAuditCmd) -// rotAuditCmd.Flags().StringVarP(&stores, "stores", "s", "", "CSV file containing cert stores to enroll into") -// rotAuditCmd.Flags().StringVarP( -// &addCerts, "add-certs", "a", "", -// "CSV file containing cert(s) to enroll into the defined cert stores", -// ) -// rotAuditCmd.Flags().StringVarP( -// &removeCerts, "remove-certs", "r", "", -// "CSV file containing cert(s) to remove from the defined cert stores", -// ) -// rotAuditCmd.Flags().IntVarP( -// &minCertsInStore, -// "min-certs", -// "m", -// -1, -// "The minimum number of certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", -// ) -// rotAuditCmd.Flags().IntVarP( -// &maxPrivateKeys, -// "max-keys", -// "k", -// -1, -// "The max number of private keys that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", -// ) -// rotAuditCmd.Flags().IntVarP( -// &maxLeaves, -// "max-leaf-certs", -// "l", -// -1, -// "The max number of non-root-certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", -// ) -// rotAuditCmd.Flags().BoolP("dry-run", "d", false, "Dry run mode") -// rotAuditCmd.Flags().StringVarP( -// &outPath, "outpath", "o", "", -// "Path to write the audit report file to. If not specified, the file will be written to the current directory.", -// ) -// -// // Root of trust `reconcile` command -// rotCmd.AddCommand(rotReconcileCmd) -// rotReconcileCmd.Flags().StringVarP(&stores, "stores", "s", "", "CSV file containing cert stores to enroll into") -// rotReconcileCmd.Flags().StringVarP( -// &addCerts, "add-certs", "a", "", -// "CSV file containing cert(s) to enroll into the defined cert stores", -// ) -// rotReconcileCmd.Flags().StringVarP( -// &removeCerts, "remove-certs", "r", "", -// "CSV file containing cert(s) to remove from the defined cert stores", -// ) -// rotReconcileCmd.Flags().IntVarP( -// &minCertsInStore, -// "min-certs", -// "m", -// -1, -// "The minimum number of certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", -// ) -// rotReconcileCmd.Flags().IntVarP( -// &maxPrivateKeys, -// "max-keys", -// "k", -// -1, -// "The max number of private keys that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", -// ) -// rotReconcileCmd.Flags().IntVarP( -// &maxLeaves, -// "max-leaf-certs", -// "l", -// -1, -// "The max number of non-root-certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", -// ) -// rotReconcileCmd.Flags().BoolP("dry-run", "d", false, "Dry run mode") -// rotReconcileCmd.Flags().BoolP("import-csv", "v", false, "Import an audit report file in CSV format.") -// rotReconcileCmd.Flags().StringVarP( -// &inputFile, "input-file", "i", reconcileDefaultFileName, -// "Path to a file generated by 'stores rot audit' command.", -// ) -// rotReconcileCmd.Flags().StringVarP( -// &outPath, "outpath", "o", "", -// "Path to write the audit report file to. If not specified, the file will be written to the current directory.", -// ) -// //rotReconcileCmd.MarkFlagsRequiredTogether("add-certs", "stores") -// //rotReconcileCmd.MarkFlagsRequiredTogether("remove-certs", "stores") -// rotReconcileCmd.MarkFlagsMutuallyExclusive("add-certs", "import-csv") -// rotReconcileCmd.MarkFlagsMutuallyExclusive("remove-certs", "import-csv") -// rotReconcileCmd.MarkFlagsMutuallyExclusive("stores", "import-csv") -// -// // Root of trust `generate` command -// rotCmd.AddCommand(rotGenStoreTemplateCmd) -// rotGenStoreTemplateCmd.Flags().StringVarP( -// &outPath, "outpath", "o", "", -// "Path to write the template file to. If not specified, the file will be written to the current directory.", -// ) -// rotGenStoreTemplateCmd.Flags().StringVarP( -// &outputFormat, "format", "f", "csv", -// "The type of template to generate. Only `csv` is supported at this time.", -// ) -// rotGenStoreTemplateCmd.Flags().Var( -// &tType, "type", -// `The type of template to generate. Only "certs|stores|actions" are supported at this time.`, -// ) -// rotGenStoreTemplateCmd.Flags().StringSliceVar( -// &storeTypes, -// "store-type", -// []string{}, -// "Multi value flag. Attempt to pre-populate the stores template with the certificate stores matching specified store types. If not specified, the template will be empty.", -// ) -// rotGenStoreTemplateCmd.Flags().StringSliceVar( -// &containerNames, -// "container-name", -// []string{}, -// "Multi value flag. Attempt to pre-populate the stores template with the certificate stores matching specified container types. If not specified, the template will be empty.", -// ) -// rotGenStoreTemplateCmd.Flags().StringSliceVar( -// &subjectNames, -// "cn", -// []string{}, -// "Subject name(s) to pre-populate the 'certs' template with. If not specified, the template will be empty. Does not work with SANs.", -// ) -// rotGenStoreTemplateCmd.Flags().StringSliceVar( -// &collections, -// "collection", -// []string{}, -// "Certificate collection name(s) to pre-populate the stores template with. If not specified, the template will be empty.", -// ) -// -// rotGenStoreTemplateCmd.RegisterFlagCompletionFunc("type", templateTypeCompletion) -// rotGenStoreTemplateCmd.MarkFlagRequired("type") -//} +import ( + "bufio" + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "io" + stdlog "log" + "os" + "strconv" + "strings" + + "github.com/Keyfactor/keyfactor-go-client/v3/api" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" +) + +type templateType string +type StoreCSVEntry struct { + ID string `json:"id"` + Type string `json:"type"` + Machine string `json:"address"` + Path string `json:"path"` + Thumbprints map[string]bool `json:"thumbprints,omitempty"` + Serials map[string]bool `json:"serials,omitempty"` + Ids map[int]bool `json:"ids,omitempty"` +} +type ROTCert struct { + ID int `json:"id,omitempty"` + ThumbPrint string `json:"thumbprint,omitempty"` + CN string `json:"cn,omitempty"` + Locations []api.CertificateLocations `json:"locations,omitempty"` +} +type ROTAction struct { + StoreID string `json:"store_id,omitempty" mapstructure:"StoreID,omitempty"` + StoreType string `json:"store_type,omitempty" mapstructure:"StoreType,omitempty"` + StorePath string `json:"store_path,omitempty" mapstructure:"StorePath,omitempty"` + Thumbprint string `json:"thumbprint,omitempty" mapstructure:"Thumbprint,omitempty"` + Alias string `json:"alias,omitempty" mapstructure:"Alias,omitempty"` + CertID int `json:"cert_id,omitempty" mapstructure:"CertID,omitempty"` + AddCert bool `json:"add,omitempty" mapstructure:"AddCert,omitempty"` + RemoveCert bool `json:"remove,omitempty" mapstructure:"RemoveCert,omitempty"` +} + +const ( + tTypeCerts templateType = "certs" + reconcileDefaultFileName string = "rot_audit.csv" +) + +var ( + AuditHeader = []string{ + "Thumbprint", + "CertID", + "SubjectName", + "Issuer", + "StoreID", + "StoreType", + "Machine", + "Path", + "AddCert", + "RemoveCert", + "Deployed", + "AuditDate", + } + ReconciledAuditHeader = []string{ + "Thumbprint", + "CertID", + "SubjectName", + "Issuer", + "StoreID", + "StoreType", + "Machine", + "Path", + "AddCert", + "RemoveCert", + "Deployed", + "ReconciledDate", + } + StoreHeader = []string{ + "StoreID", + "StoreType", + "StoreMachine", + "StorePath", + "ContainerId", + "ContainerName", + "LastQueriedDate", + } + CertHeader = []string{"Thumbprint", "SubjectName", "Issuer", "CertID", "Locations", "LastQueriedDate"} +) + +// String is used both by fmt.Print and by Cobra in help text +func (e *templateType) String() string { + return string(*e) +} + +// Set must have pointer receiver, so it doesn't change the value of a copy +func (e *templateType) Set(v string) error { + switch v { + case "certs", "stores", "actions": + *e = templateType(v) + return nil + default: + return errors.New(`must be one of "certs", "stores", or "actions"`) + } +} + +// Type is only used in help text +func (e *templateType) Type() string { + return "string" +} + +func templateTypeCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{ + "certs\tGenerates template CSV for certificate input to be used w/ `--add-certs` or `--remove-certs`", + "stores\tGenerates template CSV for certificate input to be used w/ `--stores`", + "actions\tGenerates template CSV for certificate input to be used w/ `--actions`", + }, cobra.ShellCompDirectiveDefault +} + +func generateAuditReport( + addCerts map[string]string, + removeCerts map[string]string, + stores map[string]StoreCSVEntry, + outpath string, + kfClient *api.Client, +) ([][]string, map[string][]ROTAction, error) { + log.Debug().Msg("Entering generateAuditReport") + var ( + data [][]string + ) + + data = append(data, AuditHeader) + var csvFile *os.File + var fErr error + if outpath == "" { + csvFile, fErr = os.Create(reconcileDefaultFileName) + outpath = reconcileDefaultFileName + } else { + csvFile, fErr = os.Create(outpath) + } + + if fErr != nil { + log.Error(). + Str("file", csvFile.Name()). + Msg("Error creating audit file") + outputError(fErr, true, outputFormat) + + } + csvWriter := csv.NewWriter(csvFile) + cErr := csvWriter.Write(AuditHeader) + if cErr != nil { + log.Error(). + Str("file", csvFile.Name()). + Err(cErr). + Msg("Error writing audit header") + outputError(cErr, true, outputFormat) + } + actions := make(map[string][]ROTAction) + + for _, cert := range addCerts { + certLookupReq := api.GetCertificateContextArgs{ + IncludeMetadata: boolToPointer(true), + IncludeLocations: boolToPointer(true), + CollectionId: nil, + Thumbprint: cert, + Id: 0, + } + certLookup, err := kfClient.GetCertificateContext(&certLookupReq) + if err != nil { + fmt.Printf("[ERROR] looking up certificate %s: %s\n", cert, err) + log.Printf("[ERROR] looking up cert: %s\n%v", cert, err) + continue + } + certID := certLookup.Id + certIDStr := strconv.Itoa(certID) + for _, store := range stores { + if _, ok := store.Thumbprints[cert]; ok { + // Cert is already in the store do nothing + row := []string{ + cert, + certIDStr, + certLookup.IssuedDN, + certLookup.IssuerDN, + store.ID, + store.Type, + store.Machine, + store.Path, + "false", + "false", + "true", + getCurrentTime(""), + } + data = append(data, row) + wErr := csvWriter.Write(row) + if wErr != nil { + log.Error(). + Str("file", csvFile.Name()). + Err(wErr). + Msg("Error writing audit row") + outputError(wErr, false, outputFormat) + + } + } else { + // Cert is not deployed to this store and will need to be added + row := []string{ + cert, + certIDStr, + certLookup.IssuedDN, + certLookup.IssuerDN, + store.ID, + store.Type, + store.Machine, + store.Path, + "true", + "false", + "false", + getCurrentTime(""), + } + data = append(data, row) + wErr := csvWriter.Write(row) + if wErr != nil { + log.Error(). + Err(wErr). + Str("file", csvFile.Name()). + Msg("Error writing audit row") + outputError(wErr, false, outputFormat) + + } + actions[cert] = append( + actions[cert], ROTAction{ + Thumbprint: cert, + //TODO: add Alias + CertID: certID, + StoreID: store.ID, + StoreType: store.Type, + StorePath: store.Path, + AddCert: true, + RemoveCert: false, + }, + ) + } + } + } + for _, cert := range removeCerts { + certLookupReq := api.GetCertificateContextArgs{ + IncludeMetadata: boolToPointer(true), + IncludeLocations: boolToPointer(true), + CollectionId: nil, + Thumbprint: cert, + Id: 0, + } + certLookup, err := kfClient.GetCertificateContext(&certLookupReq) + if err != nil { + log.Printf("[ERROR] looking up cert: %s", err) + continue + } + certID := certLookup.Id + certIDStr := strconv.Itoa(certID) + for _, store := range stores { + if _, ok := store.Thumbprints[cert]; ok { + // Cert is deployed to this store and will need to be removed + row := []string{ + cert, + certIDStr, + certLookup.IssuedDN, + certLookup.IssuerDN, + store.ID, + store.Type, + store.Machine, + store.Path, + "false", + "true", + "true", + getCurrentTime(""), + } + data = append(data, row) + wErr := csvWriter.Write(row) + if wErr != nil { + fmt.Printf("%s", wErr) + log.Printf("[ERROR] writing row to CSV: %s", wErr) + } + actions[cert] = append( + actions[cert], ROTAction{ + Thumbprint: cert, + CertID: certID, + StoreID: store.ID, + StoreType: store.Type, + StorePath: store.Path, + AddCert: false, + RemoveCert: true, + }, + ) + } else { + // Cert is not deployed to this store do nothing + row := []string{ + cert, + certIDStr, + certLookup.IssuedDN, + certLookup.IssuerDN, + store.ID, + store.Type, + store.Machine, + store.Path, + "false", + "false", + "false", + getCurrentTime(""), + } + data = append(data, row) + wErr := csvWriter.Write(row) + if wErr != nil { + fmt.Printf("%s", wErr) + log.Printf("[ERROR] writing row to CSV: %s", wErr) + } + } + } + } + csvWriter.Flush() + ioErr := csvFile.Close() + if ioErr != nil { + fmt.Println(ioErr) + log.Printf("[ERROR] closing audit file: %s", ioErr) + } + fmt.Printf("Audit report written to %s\n", outpath) + return data, actions, nil +} + +func reconcileRoots(actions map[string][]ROTAction, kfClient *api.Client, reportFile string, dryRun bool) error { + log.Debug().Msg("entered reconcileRoots") + if len(actions) == 0 { + log.Info().Msg("No actions to take, roots are up-to-date.") + return nil + } + rFileName := fmt.Sprintf("%s_reconciled.csv", strings.Split(reportFile, ".csv")[0]) + csvFile, fErr := os.Create(rFileName) + if fErr != nil { + log.Error(). + Err(fErr). + Str("file", rFileName). + Msg("Error creating audit file") + outputError(fErr, true, outputFormat) + return fErr + } + defer csvFile.Close() + + csvWriter := csv.NewWriter(csvFile) + cErr := csvWriter.Write(ReconciledAuditHeader) + if cErr != nil { + log.Debug(). + Str("file", csvFile.Name()). + Err(cErr). + Msg("Error writing audit header") + outputError(cErr, true, outputFormat) + return cErr + } + for thumbprint, action := range actions { + log.Debug(). + Str("thumbprint", thumbprint). + Interface("action", action). + Msg("Processing thumbprint") + for _, a := range action { + if a.AddCert { + log.Info(). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Str("storePath", a.StorePath). + Msg("Adding cert to store") + if !dryRun { + log.Debug(). + Msg("Not a dry run") + + cStore := api.CertificateStore{ + CertificateStoreId: a.StoreID, + Overwrite: true, + Alias: a.Thumbprint, //TODO: Support non-thumbprint alias + //Alias: "", + } + + var stores []api.CertificateStore + stores = append(stores, cStore) + schedule := &api.InventorySchedule{ + Immediate: boolToPointer(true), + } + addReq := api.AddCertificateToStore{ + CertificateId: a.CertID, + CertificateStores: &stores, + InventorySchedule: schedule, + } + log.Debug(). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Msg("Adding cert to store") + + addReqJSON, _ := json.Marshal(addReq) + + log.Debug(). + Str("addReqJSON", string(addReqJSON)). + Msg("Request payload") + _, err := kfClient.AddCertificateToStores(&addReq) + if err != nil { + log.Error(). + Err(err). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Str("storePath", a.StorePath). + Msg("Error adding cert to store") + outputError(err, true, outputFormat) + continue + } + } else { + log.Info(). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Str("storePath", a.StorePath). + Msg("This is a dry run, would have added cert to store") + } + } else if a.RemoveCert { + if !dryRun { + log.Info(). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Str("storePath", a.StorePath). + Msg("Removing cert from store") + + cStore := api.CertificateStore{ + CertificateStoreId: a.StoreID, + Alias: a.Thumbprint, + } + var stores []api.CertificateStore + stores = append(stores, cStore) + schedule := &api.InventorySchedule{ + Immediate: boolToPointer(true), + } + removeReq := api.RemoveCertificateFromStore{ + CertificateId: a.CertID, + CertificateStores: &stores, + InventorySchedule: schedule, + } + _, err := kfClient.RemoveCertificateFromStores(&removeReq) + if err != nil { + fmt.Printf( + "[ERROR] removing cert %s (ID: %d) from store %s (%s): %s\n", + a.Thumbprint, + a.CertID, + a.StoreID, + a.StorePath, + err, + ) + log.Error(). + Err(err). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Str("storePath", a.StorePath). + Msg("Error removing cert from store") + } + } else { + log.Info(). + Str("thumbprint", thumbprint). + Str("store", a.StoreID). + Str("storePath", a.StorePath). + Msg("This is a dry run, would have removed cert from store") + } + } + } + } + log.Debug().Msg("exiting reconcileRoots") + return nil +} + +func readCertsFile(certsFilePath string, kfclient *api.Client) (map[string]string, error) { + // Read in the cert CSV + csvFile, _ := os.Open(certsFilePath) + reader := csv.NewReader(bufio.NewReader(csvFile)) + certEntries, _ := reader.ReadAll() + var certs = make(map[string]string) + for _, entry := range certEntries { + switch entry[0] { + case "CertID", "thumbprint", "id", "CertId", "Thumbprint": + continue // Skip header + } + certs[entry[0]] = entry[0] + } + return certs, nil +} + +func isRootStore( + st *api.GetCertificateStoreResponse, + invs *[]api.CertStoreInventory, + minCerts int, + maxKeys int, + maxLeaf int, +) bool { + leafCount := 0 + keyCount := 0 + certCount := 0 + + log.Debug(). + Int("minCerts", minCerts). + Int("maxKeys", maxKeys). + Int("maxLeaf", maxLeaf). + Msg(fmt.Sprintf(DebugFuncExit, "isRootStore")) + + if invs == nil || len(*invs) == 0 { + nullInvErr := fmt.Errorf("nil inventory response from Keyfactor Command for store '%s'", st.Id) + log.Error().Err(nullInvErr).Str("store", st.Id).Msg("nil or empty inventory returned by Keyfactor Command") + return false + } else if st == nil { + nullStoreErr := fmt.Errorf("nil store response from Keyfactor Command for store '%s'", st.Id) + log.Error().Err(nullStoreErr).Str("store", st.Id).Msg("nil or empty store returned by Keyfactor Command") + return false + } + + for _, inv := range *invs { + certCount += len(inv.Certificates) + log.Debug(). + Int("certCount", certCount). + Str("name", inv.Name). + Msg("processing inventory") + + for _, cert := range inv.Certificates { + if cert.IssuedDN != cert.IssuerDN { + log.Debug().Str("dn", cert.IssuedDN).Msg("is a leaf cert") + leafCount++ + } else { + log.Debug().Str("dn", cert.IssuedDN).Msg("is a root cert") + } + + //TODO: Do we need to look up if a cert has a private key? If so how does one know the private key isdeployed to the store? + //if inv.Parameters["PrivateKeyEntry"] == "Yes" { + // keyCount++ + //} + } + } + if certCount < minCerts && minCerts >= 0 { + log.Debug(). + Str("store", st.Id). + Int("certCount", certCount). + Int("minCerts", minCerts). + Msg("store has too few certs") + + return false + } + if leafCount > maxLeaf && maxLeaf >= 0 { + log.Debug(). + Str("store", st.Id). + Int("certCount", certCount). + Int("minCerts", minCerts). + Msg("store has too many leaf certs") + + return false + } + + if keyCount > maxKeys && maxKeys >= 0 { + log.Debug(). + Str("store", st.Id). + Int("certCount", certCount). + Int("minCerts", minCerts). + Msg("store has too many keys") + return false + } + + log.Debug(). + Str("store", st.Id). + Int("certCount", certCount). + Int("minCerts", minCerts). + Msg("store is a root store") + + log.Debug().Msg(fmt.Sprintf(DebugFuncExit, "isRootStore")) + return true +} + +var ( + rotCmd = &cobra.Command{ + Use: "rot", + Short: "Root of trust utility", + Long: `Root of trust allows you to manage your trusted roots using Keyfactor certificate stores. +For example if you wish to add a list of "root" certs to a list of certificate stores you would simply generate and fill +out the template CSV file. These template files can be generated with the following commands: +kfutil stores rot generate-template --type certs +kfutil stores rot generate-template --type stores +Once those files are filled out you can use the following command to add the certs to the stores: +kfutil stores rot audit --certs-file --stores-file +Will generate a CSV report file 'rot_audit.csv' of what actions will be taken. If those actions are correct you can run +the following command to actually perform the actions: +kfutil stores rot reconcile --certs-file --stores-file +OR if you want to use the audit report file generated you can run this command: +kfutil stores rot reconcile --import-csv +`, + } + rotAuditCmd = &cobra.Command{ + Use: "audit", + Aliases: nil, + SuggestFor: nil, + Short: "Audit generates a CSV report of what actions will be taken based on input CSV files.", + Long: `Root of Trust Audit: Will read and parse inputs to generate a report of certs that need to be added or removed from the "root of trust" stores.`, + Example: "", + ValidArgs: nil, + ValidArgsFunction: nil, + Args: nil, + ArgAliases: nil, + BashCompletionFunction: "", + Deprecated: "", + Annotations: nil, + Version: "", + PersistentPreRun: nil, + PersistentPreRunE: nil, + PreRun: nil, + PreRunE: nil, + RunE: func(cmd *cobra.Command, args []string) error { + // Global flags + cmd.SilenceUsage = true + // expEnabled checks + isExperimental := false + debugErr := warnExperimentalFeature(expEnabled, isExperimental) + if debugErr != nil { + return debugErr + } + stdlog.SetOutput(io.Discard) + informDebug(debugFlag) + + var lookupFailures []string + // Authenticate + kfClient, cErr := initClient(false) + if cErr != nil { + log.Error().Err(cErr).Msg("unable to authenticate") + return cErr + } + + // Local flags + storesFile, _ := cmd.Flags().GetString("stores") + addRootsFile, _ := cmd.Flags().GetString("add-certs") + removeRootsFile, _ := cmd.Flags().GetString("remove-certs") + minCerts, _ := cmd.Flags().GetInt("min-certs") + maxLeaves, _ := cmd.Flags().GetInt("max-leaf-certs") + maxKeys, _ := cmd.Flags().GetInt("max-keys") + dryRun, _ := cmd.Flags().GetBool("dry-run") + outpath, _ := cmd.Flags().GetString("outpath") + // Read in the stores CSV + log.Debug(). + Str("storesFile", storesFile). + Str("addRootsFile", addRootsFile). + Str("removeRootsFile", removeRootsFile). + Bool("dryRun", dryRun). + Int("minCerts", minCerts). + Int("maxLeaves", maxLeaves). + Int("maxKeys", maxKeys). + Str("outpath", outpath). + Msg("flags") + + // Read in the stores CSV + csvFile, _ := os.Open(storesFile) + reader := csv.NewReader(bufio.NewReader(csvFile)) + storeEntries, _ := reader.ReadAll() + var stores = make(map[string]StoreCSVEntry) + validHeader := false + for _, entry := range storeEntries { + if strings.EqualFold(strings.Join(entry, ","), strings.Join(StoreHeader, ",")) { + validHeader = true + continue // Skip header + } + if !validHeader { + fmt.Printf("[ERROR] Invalid header in stores file. Expected: %s", strings.Join(StoreHeader, ",")) + log.Error(). + Str("expectedHeader", strings.Join(StoreHeader, ",")). + Msg("Invalid header in stores file") + } + apiResp, err := kfClient.GetCertificateStoreByID(entry[0]) + if err != nil { + log.Error(). + Err(err). + Str("store", entry[0]). + Msg("Error getting store from Keyfactor Command") + _ = append(lookupFailures, strings.Join(entry, ",")) + continue + } + + inventory, invErr := kfClient.GetCertStoreInventory(entry[0]) + if invErr != nil { + log.Error().Err(invErr).Str("store", entry[0]).Msg("Error getting store inventory") + outputError(invErr, true, outputFormat) + return invErr + } + + if inventory == nil { + invalidRespErr := fmt.Errorf( + "invalid inventory response from Keyfactor Command for store '%s'", + entry[0], + ) + log.Error().Err(invalidRespErr).Str("store", entry[0]).Msg("invalid response") + outputError(invalidRespErr, true, outputFormat) + return invalidRespErr + } + //var inventory []api.CertStoreInventory //TODO: Update this to use SDK inventory + + if !isRootStore(apiResp, inventory, minCerts, maxLeaves, maxKeys) { + outputResult(fmt.Sprintf("Store %s is not a root store, skipping.\n", entry[0]), outputFormat) + log.Error(). + Str("store", entry[0]). + Str("id", apiResp.Id). + Int("type", apiResp.CertStoreType). + Str("machine", apiResp.ClientMachine). + Str("path", apiResp.StorePath). + Msg("Store is not a root store") + continue + } else { + outputResult(fmt.Sprintf("Store %s is a root store.\n", entry[0]), outputFormat) + log.Info(). + Str("store", entry[0]). + Str("id", apiResp.Id). + Int("type", apiResp.CertStoreType). + Str("machine", apiResp.ClientMachine). + Str("path", apiResp.StorePath). + Msg("Is a root store") + } + + stores[entry[0]] = StoreCSVEntry{ + ID: entry[0], + Type: entry[1], + Machine: entry[2], + Path: entry[3], + Thumbprints: make(map[string]bool), + Serials: make(map[string]bool), + Ids: make(map[int]bool), + } + + log.Debug().Str("store", entry[0]). + Str("id", apiResp.Id). + Int("type", apiResp.CertStoreType). + Str("machine", apiResp.ClientMachine). + Str("path", apiResp.StorePath). + Msg("Iterating store inventory") + for _, cert := range *inventory { + thumb := cert.Thumbprints + + log.Debug().Str("store", entry[0]). + Str("id", apiResp.Id). + Int("type", apiResp.CertStoreType). + Str("machine", apiResp.ClientMachine). + Str("path", apiResp.StorePath). + Msg("Iterating inventory thumbprints") + for _, v := range thumb { + stores[entry[0]].Thumbprints[v] = true + } + log.Debug().Str("store", entry[0]). + Str("id", apiResp.Id). + Int("type", apiResp.CertStoreType). + Str("machine", apiResp.ClientMachine). + Str("path", apiResp.StorePath). + Msg("Iterating inventory serial numbers") + for _, v := range cert.Serials { + stores[entry[0]].Serials[v] = true + } + + log.Debug().Str("store", entry[0]). + Str("id", apiResp.Id). + Int("type", apiResp.CertStoreType). + Str("machine", apiResp.ClientMachine). + Str("path", apiResp.StorePath). + Msg("Iterating certificate IDs") + for _, v := range cert.Ids { + stores[entry[0]].Ids[v] = true + } + } + + } + + // Read in the add addCerts CSV + var certsToAdd = make(map[string]string) + if addRootsFile != "" { + var rcfErr error + + log.Debug(). + Str("addRootsFile", addRootsFile). + Msg("Reading addCerts file") + certsToAdd, rcfErr = readCertsFile(addRootsFile, kfClient) + if rcfErr != nil { + outputError(rcfErr, true, outputFormat) + log.Error(). + Err(rcfErr). + Msg("reading addCerts file") + return rcfErr + } + addCertsJSON, _ := json.Marshal(certsToAdd) + log.Debug().Str("addCerts", string(addCertsJSON)).Msg("addCerts") + } else { + log.Debug().Msg("No addCerts file specified") + } + + // Read in the remove removeCerts CSV + var certsToRemove = make(map[string]string) + if removeRootsFile != "" { + var rcfErr error + certsToRemove, rcfErr = readCertsFile(removeRootsFile, kfClient) + if rcfErr != nil { + outputError(rcfErr, true, outputFormat) + log.Error().Err(rcfErr).Msg("failed reading removeCerts file") + return rcfErr + } + removeCertsJSON, _ := json.Marshal(certsToRemove) + log.Debug().Str("removeCerts", string(removeCertsJSON)).Msg("removeCerts") + } else { + log.Debug().Msg("No removeCerts file specified") + } + + log.Debug(). + Str("outpath", outpath). + Interface("certsToAdd", certsToAdd). + Interface("certsToRemove", certsToRemove). + Msg("Generating audit report") + _, _, gErr := generateAuditReport(certsToAdd, certsToRemove, stores, outpath, kfClient) + if gErr != nil { + outputError(gErr, true, outputFormat) + log.Error().Err(gErr).Msg("failed generating audit report") + return gErr + } + + return nil + }, + Run: nil, + PostRun: nil, + PostRunE: nil, + PersistentPostRun: nil, + PersistentPostRunE: nil, + FParseErrWhitelist: cobra.FParseErrWhitelist{}, + CompletionOptions: cobra.CompletionOptions{}, + TraverseChildren: false, + Hidden: false, + SilenceErrors: false, + SilenceUsage: false, + DisableFlagParsing: false, + DisableAutoGenTag: false, + DisableFlagsInUseLine: false, + DisableSuggestions: false, + SuggestionsMinimumDistance: 0, + } + rotReconcileCmd = &cobra.Command{ + Use: "reconcile", + Aliases: nil, + SuggestFor: nil, + Short: "Reconcile either takes in or will generate an audit report and then add/remove certs as needed.", + Long: `Root of Trust (rot): Will parse either a combination of CSV files that define certs to +add and/or certs to remove with a CSV of certificate stores or an audit CSV file. If an audit CSV file is provided, the +add and remove actions defined in the audit file will be immediately executed. If a combination of CSV files are provided, +the utility will first generate an audit report and then execute the add/remove actions defined in the audit report.`, + Example: "", + ValidArgs: nil, + ValidArgsFunction: nil, + Args: nil, + ArgAliases: nil, + BashCompletionFunction: "", + Deprecated: "", + Annotations: nil, + Version: "", + PersistentPreRun: nil, + PersistentPreRunE: nil, + PreRun: nil, + PreRunE: nil, + RunE: func(cmd *cobra.Command, args []string) error { + // Global flags + cmd.SilenceUsage = true + // expEnabled checks + isExperimental := false + debugErr := warnExperimentalFeature(expEnabled, isExperimental) + if debugErr != nil { + return debugErr + } + stdlog.SetOutput(io.Discard) + informDebug(debugFlag) + + var lookupFailures []string + // Authenticate + kfClient, cErr := initClient(false) + if cErr != nil { + log.Error().Err(cErr).Msg("unable to authenticate") + return cErr + } + + // Local flags + storesFile, _ := cmd.Flags().GetString("stores") + addRootsFile, _ := cmd.Flags().GetString("add-certs") + removeRootsFile, _ := cmd.Flags().GetString("remove-certs") + minCerts, _ := cmd.Flags().GetInt("min-certs") + maxLeaves, _ := cmd.Flags().GetInt("max-leaf-certs") + maxKeys, _ := cmd.Flags().GetInt("max-keys") + dryRun, _ := cmd.Flags().GetBool("dry-run") + outpath, _ := cmd.Flags().GetString("outpath") + isCSV, _ := cmd.Flags().GetBool("import-csv") + reportFile, _ := cmd.Flags().GetString("input-file") + // Read in the stores CSV + log.Debug(). + Str("storesFile", storesFile). + Str("addRootsFile", addRootsFile). + Str("removeRootsFile", removeRootsFile). + Bool("dryRun", dryRun). + Int("minCerts", minCerts). + Int("maxLeaves", maxLeaves). + Int("maxKeys", maxKeys). + Str("outpath", outpath). + Bool("isCSV", isCSV). + Str("reportFile", reportFile). + Msg("flags") + + // Parse existing audit report + if isCSV && reportFile != "" { + log.Debug(). + Str("reportFile", reportFile). + Msg("reading CSV audit report") + // Read in the CSV + csvFile, err := os.Open(reportFile) + if err != nil { + outputError(err, true, outputFormat) + log.Error(). + Err(err). + Str("reportFile", reportFile). + Msg("failed opening CSV file") + return err + } + validHeader := false + + log.Debug(). + Str("reportFile", reportFile). + Msg("parsing CSV audit report") + aCSV := csv.NewReader(csvFile) + aCSV.FieldsPerRecord = -1 + inFile, cErr := aCSV.ReadAll() + if cErr != nil { + log.Error().Err(cErr).Str("reportFile", reportFile). + Msg("failed parsing CSV file") + } + actions := make(map[string][]ROTAction) + fieldMap := make(map[int]string) + + log.Debug(). + Str("reportFile", reportFile). + Msg("mapping CSV header") + for i, field := range AuditHeader { + fieldMap[i] = field + } + for ri, row := range inFile { + if strings.EqualFold(strings.Join(row, ","), strings.Join(AuditHeader, ",")) { + validHeader = true + log.Debug(). + Str("reportFile", reportFile). + Msg("skipping header") + continue + } + if !validHeader { + log.Error(). + Str("reportFile", reportFile). + Str("expectedHeader", strings.Join(AuditHeader, ",")). + Str("inputFileHeader", strings.Join(row, ",")). + Msg("invalid header") + log.Debug(). + Int("row", ri). + Str("reportFile", reportFile). + Msg("searching for valid header") + } + + action := make(map[string]interface{}) + + log.Debug().Int("row", ri).Msg("processing row data") + for i, field := range row { + fieldInt, iErr := strconv.Atoi(field) + if iErr != nil { + log.Debug().Int("row", ri).Str("field", field).Msg("field is not an integer") + action[fieldMap[i]] = field + } else { + log.Debug().Int("row", ri).Str("field", field).Msg("field is an integer") + action[fieldMap[i]] = fieldInt + } + } + + addCertStr, aOk := action["AddCert"].(string) + if !aOk { + addCertStr = "" + } + addCert, acErr := strconv.ParseBool(addCertStr) + if acErr != nil { + addCert = false + } + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"RemoveCert\" col") + removeCertStr, rOk := action["RemoveCert"].(string) + if !rOk { + removeCertStr = "" + } + removeCert, rcErr := strconv.ParseBool(removeCertStr) + if rcErr != nil { + removeCert = false + } + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"StoreType\" col") + sType, sOk := action["StoreType"].(string) + if !sOk { + sType = "" + } + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"Path\" col") + sPath, pOk := action["Path"].(string) + if !pOk { + sPath = "" + } + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"Thumbprint\" col") + tp, tpOk := action["Thumbprint"].(string) + if !tpOk { + tp = "" + } + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"Alias\" col") + alias, aliasOk := action["Alias"].(string) + if !aliasOk { + alias = "" + } + log.Debug().Str("alias", alias).Send() + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"CertID\" col") + cid, cidOk := action["CertID"].(int) + if !cidOk { + cid = -1 + } + + if !tpOk && !cidOk { + outputError( + fmt.Errorf( + fmt.Sprintf( + "Missing Thumbprint or CertID for row '%d' in report file '%s'", + ri, + reportFile, + ), + ), false, outputFormat, + ) + log.Error(). + Str("reportFile", reportFile). + Int("row", ri).Msg("missing thumbprint or certID for row") + continue + } + + log.Debug(). + Str("reportFile", reportFile). + Int("row", ri). + Msg("parsing \"StoreID\" col") + sId, sIdOk := action["StoreID"].(string) + if !sIdOk { + sIdErr := fmt.Errorf("missing 'StoreID' for row '%d' in report file '%s'", ri, reportFile) + outputError(sIdErr, true, outputFormat) + log.Error().Err(sIdErr).Str("reportFile", reportFile). + Int("row", ri).Msg("invalid action") + continue + } + + if cid == -1 && tp != "" { + log.Debug().Msg("creating lookup by thumbprint request") + certLookupReq := api.GetCertificateContextArgs{ + IncludeMetadata: boolToPointer(true), + IncludeLocations: boolToPointer(true), + CollectionId: nil, + Thumbprint: tp, + Id: 0, + } + certLookup, certLookupErr := kfClient.GetCertificateContext(&certLookupReq) + if certLookupErr != nil { + outputError(certLookupErr, true, outputFormat) + log.Error().Err(certLookupErr).Str("thumbprint", tp).Msg("failed looking up cert") + continue + } + cid = certLookup.Id + } + + log.Debug(). + Int("row", ri). + Str("reportFile", reportFile). + Str("StoreID", sId). + Str("StoreType", sType). + Str("Path", sPath). + Str("Thumbprint", tp). + Str("CertID", fmt.Sprintf("%d", cid)). + Bool("AddCert", addCert). + Bool("RemoveCert", removeCert). + Msg("creating ROTAction") + a := ROTAction{ + StoreID: sId, + StoreType: sType, + StorePath: sPath, + Thumbprint: tp, + CertID: cid, + AddCert: addCert, + RemoveCert: removeCert, + } + + actions[a.Thumbprint] = append(actions[a.Thumbprint], a) + } + if len(actions) == 0 { + outputResult( + "No reconciliation actions to take, root stores are up-to-date. Exiting.", + outputFormat, + ) + log.Info(). + Str("reportFile", reportFile). + Msg("No reconciliation actions to take, root stores are up-to-date. Exiting.") + return nil + } + + log.Debug().Msg("reconciling roots") + rErr := reconcileRoots(actions, kfClient, reportFile, dryRun) + if rErr != nil { + log.Error(). + Err(rErr). + Str("reportFile", reportFile). + Msg("failed reconciling roots") + return rErr + } + defer csvFile.Close() + + jobStatusURL := fmt.Sprintf( + "https://%s/KeyfactorPortal/AgentJobStatus/Index", + kfClient.AuthClient.GetServerConfig().Host, + ) + + log.Info().Str("reportFile", reportFile). + Str("jobStatusURL", jobStatusURL). + Msg("reconciliation complete") + outputResult("Reconciliation complete. Job status URL: "+jobStatusURL, outputFormat) + return nil + } else { + // Read in the stores CSV + log.Debug(). + Str("storesFile", storesFile). + Msg("opening stores CSV file") + csvFile, csvErr := os.Open(storesFile) + if csvErr != nil { + outputError(csvErr, true, outputFormat) + log.Error(). + Err(csvErr). + Str("storesFile", storesFile). + Msg("failed opening CSV file") + return csvErr + } + + defer csvFile.Close() + + log.Debug(). + Str("storesFile", storesFile). + Msg("reading stores CSV file data") + reader := csv.NewReader(bufio.NewReader(csvFile)) + storeEntries, stErr := reader.ReadAll() + if stErr != nil { + log.Error().Err(stErr).Str("storesFile", storesFile). + Msg("failed reading CSV file") + return stErr + } + if len(storeEntries) == 0 { + noStoresErr := fmt.Errorf("no stores found in CSV file") + outputError(noStoresErr, true, outputFormat) + log.Error(). + Str("storesFile", storesFile). + Err(noStoresErr). + Send() + return fmt.Errorf("no stores found in CSV file") + } + + log.Debug().Str("storesFile", storesFile). + Int("storeEntries", len(storeEntries)). + Msg("processing stores CSV file data") + var stores = make(map[string]StoreCSVEntry) + for i, entry := range storeEntries { + if entry[0] == "StoreID" || entry[0] == "StoreId" || i == 0 { + log.Debug().Str("storesFile", storesFile).Msg("skipping file header") + continue // Skip header + } + + log.Debug().Str("storesFile", storesFile). + Str("StoreID", entry[0]). + Msg("calling GetCertificateStoreByID for store") + apiResp, err := kfClient.GetCertificateStoreByID(entry[0]) + if err != nil { + log.Error(). + Err(err).Str("StoreID", entry[0]). + Msg("unable to get certificate by ID") + lookupFailures = append(lookupFailures, entry[0]) + continue + } + //inventory, invErr := kfClient.GetCertStoreInventoryV1(entry[0]) + inventory, invErr := kfClient.GetCertStoreInventory(entry[0]) + if invErr != nil { + outputError(invErr, true, outputFormat) + log.Error(). + Err(invErr). + Str("storesFile", storesFile). + Str("StoreID", entry[0]). + Msg("unable to get inventory") + continue + } + + if !isRootStore(apiResp, inventory, minCerts, maxLeaves, maxKeys) { + log.Info().Str("storesFile", storesFile). + Str("StoreID", entry[0]). + Int("minCerts", minCerts). + Int("maxLeaves", maxLeaves). + Int("maxKeys", maxKeys). + Msg("is not a root store") + //lookupFailures = append(lookupFailures, entry[0]) + continue + } else { + log.Info().Str("storesFile", storesFile). + Str("StoreID", entry[0]). + Msg("is a root store") + } + + stores[entry[0]] = StoreCSVEntry{ + ID: entry[0], + Type: entry[1], + Machine: entry[2], + Path: entry[3], + Thumbprints: make(map[string]bool), + Serials: make(map[string]bool), + Ids: make(map[int]bool), + } + for _, cert := range *inventory { + thumb := cert.Thumbprints + for _, v := range thumb { + stores[entry[0]].Thumbprints[v] = true + } + for _, v := range cert.Serials { + stores[entry[0]].Serials[v] = true + } + for _, v := range cert.Ids { + stores[entry[0]].Ids[v] = true + } + } + + } + if len(lookupFailures) > 0 { + failedErr := fmt.Errorf( + "the following stores were not found: %s", + strings.Join(lookupFailures, ","), + ) + outputError(failedErr, true, outputFormat) + log.Error(). + Err(failedErr). + Strs("lookupFailures", lookupFailures). + Msg("failed to lookup stores") + return failedErr + } + if len(stores) == 0 { + noStoresErr := fmt.Errorf("no stores found in CSV file %s", storesFile) + outputError(noStoresErr, true, outputFormat) + return noStoresErr + } + // Read in the add addCerts CSV + var certsToAdd = make(map[string]string) + if addRootsFile != "" { + log.Debug().Str("addRootsFile", addRootsFile).Msg("calling readCerts") + certsToAdd, _ = readCertsFile(addRootsFile, kfClient) + //TODO: Handle error here? + } else { + log.Info().Str("addRootsFile", addRootsFile).Msg("no certs to add to trust stores") + } + + // Read in the remove removeCerts CSV + var certsToRemove = make(map[string]string) + if removeRootsFile != "" { + log.Debug().Str("removeRootsFile", removeRootsFile).Msg("calling readCerts") + certsToRemove, _ = readCertsFile(removeRootsFile, kfClient) + //TODO: Handle error here? + } else { + log.Info().Str("removeRootsFile", removeRootsFile).Msg("no certs to remove from trust stores") + } + + log.Debug(). + Str("storesFile", storesFile). + Str("addRootsFile", addRootsFile). + Interface("certsToAdd", certsToAdd). + Str("removeRootsFile", removeRootsFile). + Interface("certsToRemove", certsToRemove). + Str("outpath", outpath). + Msg("calling generateAuditReport") + _, actions, err := generateAuditReport(certsToAdd, certsToRemove, stores, outpath, kfClient) + if err != nil { + outputError(err, true, outputFormat) + log.Error().Err(err). + Str("storesFile", storesFile). + Str("addRootsFile", addRootsFile). + Str("removeRootsFile", removeRootsFile). + Str("outpath", outpath). + Msg("failed to generate audit report") + return err + } + if len(actions) == 0 { + log.Info().Str("storesFile", storesFile). + Str("addRootsFile", addRootsFile). + Str("removeRootsFile", removeRootsFile). + Str("outpath", outpath). + Msg("no reconciliation actions to take, root stores are up-to-date") + outputResult( + "No reconciliation actions to take, root stores are up-to-date. Exiting.", + outputFormat, + ) + return nil + } + + log.Debug().Str("reportFile", reportFile).Msg("calling reconcileRoots") + rErr := reconcileRoots(actions, kfClient, reportFile, dryRun) + if rErr != nil { + outputError(rErr, true, outputFormat) + log.Error(). + Err(rErr). + Str("reportFile", reportFile).Msg("failed reconciling roots") + return rErr + } + if lookupFailures != nil { + lookupErr := fmt.Errorf( + "the following stores could not be found: %s", + strings.Join(lookupFailures, ","), + ) + outputError(lookupErr, true, outputFormat) + log.Error(). + Err(lookupErr). + Strs("lookupFailures", lookupFailures). + Msg("failed to lookup stores") + return lookupErr + } + orchsURL := fmt.Sprintf( + "https://%s/KeyfactorPortal/AgentJobStatus/Index", + kfClient.AuthClient.GetServerConfig().Host, + ) + log.Info(). + Str("reportFile", reportFile). + Str("orchsURL", orchsURL). + Msg("reconciliation complete") + outputResult( + fmt.Sprintf("Reconciliation completed. Check orchestrator jobs for details. %s", orchsURL), + outputFormat, + ) + return nil + } + + }, + Run: nil, + PostRun: nil, + PostRunE: nil, + PersistentPostRun: nil, + PersistentPostRunE: nil, + FParseErrWhitelist: cobra.FParseErrWhitelist{}, + CompletionOptions: cobra.CompletionOptions{}, + TraverseChildren: false, + Hidden: false, + SilenceErrors: false, + SilenceUsage: false, + DisableFlagParsing: false, + DisableAutoGenTag: false, + DisableFlagsInUseLine: false, + DisableSuggestions: false, + SuggestionsMinimumDistance: 0, + } + rotGenStoreTemplateCmd = &cobra.Command{ + Use: "generate-template", + Aliases: nil, + SuggestFor: nil, + Short: "For generating Root Of Trust template(s)", + Long: `Root Of Trust: Will parse a CSV and attempt to deploy a cert or set of certs into a list of cert stores.`, + Example: "", + ValidArgs: nil, + ValidArgsFunction: nil, + Args: nil, + ArgAliases: nil, + BashCompletionFunction: "", + Deprecated: "", + Annotations: nil, + Version: "", + PersistentPreRun: nil, + PersistentPreRunE: nil, + PreRun: nil, + PreRunE: nil, + RunE: func(cmd *cobra.Command, args []string) error { + // Global flags + cmd.SilenceUsage = true + // expEnabled checks + isExperimental := false + debugErr := warnExperimentalFeature(expEnabled, isExperimental) + if debugErr != nil { + return debugErr + } + stdlog.SetOutput(io.Discard) + informDebug(debugFlag) + + // Authenticate + kfClient, cErr := initClient(false) + if cErr != nil { + log.Error().Err(cErr).Msg("unable to authenticate") + return cErr + } + + templateType, _ := cmd.Flags().GetString("type") + format, _ := cmd.Flags().GetString("format") + outPath, _ := cmd.Flags().GetString("outpath") + storeType, _ := cmd.Flags().GetStringSlice("store-type") + containerName, _ := cmd.Flags().GetStringSlice("container-name") + collection, _ := cmd.Flags().GetStringSlice("collection") + subjectName, _ := cmd.Flags().GetStringSlice("cn") + log.Debug().Str("templateType", templateType). + Str("format", format). + Str("outPath", outPath). + Strs("storeType", storeType). + Strs("containerName", containerName). + Strs("collection", collection). + Strs("subjectName", subjectName). + Msg("flags") + //if templateType == "" { + // return fmt.Errorf("template type must be specified") + //} + + stID := -1 + var storeData []api.GetCertificateStoreResponse + var csvStoreData [][]string + var csvCertData [][]string + var rowLookup = make(map[string]bool) + if len(storeType) != 0 { + for _, s := range storeType { + log.Debug().Str("storeType", s).Msg("processing store-type") + var sType *api.CertificateStoreType + var stErr error + if s == "all" { + log.Info().Str("storeType", s).Msg("getting all stores") + sType = &api.CertificateStoreType{ + Name: "", + ShortName: "", + Capability: "", + StoreType: 0, + ImportType: 0, + LocalStore: false, + SupportedOperations: nil, + Properties: nil, + EntryParameters: nil, + PasswordOptions: nil, + StorePathType: "", + StorePathValue: "", + PrivateKeyAllowed: "", + JobProperties: nil, + ServerRequired: false, + PowerShell: false, + BlueprintAllowed: false, + CustomAliasAllowed: "", + ServerRegistration: 0, + InventoryEndpoint: "", + InventoryJobType: "", + ManagementJobType: "", + DiscoveryJobType: "", + EnrollmentJobType: "", + } + } else { + // check if s is an int + log.Debug().Str("storeType", s).Msg("checking if store-type is an int") + sInt, err := strconv.Atoi(s) + if err == nil { + log.Debug().Str("storeType", s).Msg("calling GetCertificateStoreByID") + sType, stErr = kfClient.GetCertificateStoreTypeById(sInt) + } else { + log.Debug().Str("storeType", s).Msg("calling GetCertificateStoreByName") + sType, stErr = kfClient.GetCertificateStoreTypeByName(s) + } + if stErr != nil { + outputError(stErr, true, format) + log.Error().Err(stErr).Str("storeType", s).Msg("failed to get stores") + continue + } + stID = sType.StoreType // This is the template type ID + } + + if stID >= 0 || s == "all" { + log.Debug(). + Int("stID", stID). + Str("storeType", s). + Msg("valid store type") + params := make(map[string]interface{}) + + log.Debug().Str("storeType", s).Msg("calling ListCertificateStores") + stores, sErr := kfClient.ListCertificateStores(¶ms) + if sErr != nil { + log.Error().Err(sErr).Str("storeType", s).Msg("failed to get stores") + outputError(sErr, true, format) + return sErr + } + + if stores == nil { + invalidRespErr := fmt.Errorf("invalid response from Keyfactor Command when listing certificate stores") + log.Error().Err(invalidRespErr).Str("storeType", s).Msg("stores is nil") + outputError(invalidRespErr, true, format) + return invalidRespErr + } + log.Debug().Str("storeType", s).Msg("processing stores") + + for _, store := range *stores { + if store.CertStoreType == stID || s == "all" { + storeData = append(storeData, store) + if !rowLookup[store.Id] { + lineData := []string{ + //"StoreID", "StoreType", "StoreMachine", "StorePath", "ContainerId" + store.Id, + fmt.Sprintf("%s", sType.ShortName), + store.ClientMachine, + store.StorePath, + fmt.Sprintf("%d", store.ContainerId), + store.ContainerName, + getCurrentTime(""), + } + log.Debug().Str("storeType", s). + Strs("lineData", lineData). + Msg("adding line data") + csvStoreData = append(csvStoreData, lineData) + rowLookup[store.Id] = true + } + } + } + } + } + log.Info().Msg("lookups by store-type completed") + } + containers := len(containerName) + if containers > 0 { + log.Info(). + Int("containers", containers). + Msg("processing container-names") + for _, c := range containerName { + cStoresResp, scErr := kfClient.GetCertificateStoreByContainerID(c) + if scErr != nil { + log.Error().Err(scErr).Str("containerName", c).Msg("failed to get stores by container name") + return cErr + } + if cStoresResp == nil { + invalidRespErr := fmt.Errorf( + "invalid response from Keyfactor Command when listing stores by container name '%s'", + c, + ) + outputError(invalidRespErr, true, format) + log.Error().Err(invalidRespErr).Str("containerName", c).Msg("invalid response") + return invalidRespErr + } + for _, store := range *cStoresResp { + log.Debug(). + Str("containerName", c). + Int("storeType", store.CertStoreType). + Msg("calling GetCertificateStoreType") + sType, stErr := kfClient.GetCertificateStoreType(store.CertStoreType) + if stErr != nil { + outputError(stErr, false, format) + log.Error().Err(stErr).Str( + "containerName", + c, + ).Msg("failed to get store-type by container name") + continue + } + storeData = append(storeData, store) + if !rowLookup[store.Id] { + lineData := []string{ + // "StoreID", "StoreType", "StoreMachine", "StorePath", "ContainerId" + store.Id, + sType.ShortName, + store.ClientMachine, + store.StorePath, + fmt.Sprintf("%d", store.ContainerId), + store.ContainerName, + getCurrentTime(""), + } + log.Debug().Str("containerName", c). + Strs("lineData", lineData). + Msg("adding line data") + csvStoreData = append(csvStoreData, lineData) + rowLookup[store.Id] = true + } + } + } + log.Info().Msg("lookups by container-name completed") + } + + collections := len(collection) + if collections > 0 { + log.Info(). + Int("collections", collections). + Msg("processing collections") + for _, c := range collection { + q := make(map[string]string) + q["collection"] = c + log.Debug().Str("collection", c).Msg("calling ListCertificateStores") + certsResp, scErr := kfClient.ListCertificates(q) + if scErr != nil { + log.Error().Err(scErr).Str("collection", c).Msg("failed to list certificates by collection") + outputError(scErr, true, format) + return scErr + } + if certsResp == nil { + invalidRespErr := fmt.Errorf( + "invalid response from Keyfactor Command when listing certificates by collection '%s'", + c, + ) + outputError(invalidRespErr, true, format) + log.Error().Err(invalidRespErr).Str("collection", c).Msg("invalid response") + return invalidRespErr + } + for _, cert := range certsResp { + if !rowLookup[cert.Thumbprint] { + lineData := []string{ + // "Thumbprint", "SubjectName", "Issuer", "CertID", "Locations", "LastQueriedDate" + cert.Thumbprint, + cert.IssuedCN, + cert.IssuerDN, + fmt.Sprintf("%d", cert.Id), + fmt.Sprintf("%v", cert.Locations), + getCurrentTime(""), + } + log.Debug(). + Str("collection", c). + Strs("lineData", lineData). + Msg("adding line data") + csvCertData = append(csvCertData, lineData) + rowLookup[cert.Thumbprint] = true + } + } + } + log.Info(). + Int("collections", collections). + Msg("lookups by collection completed") + } + + cns := len(subjectName) + if cns > 0 { + log.Info(). + Int("subjectNames", cns). + Msg("processing subject-names") + for _, s := range subjectName { + q := make(map[string]string) + q["subject"] = s + + log.Debug().Str("subjectName", s).Msg("calling ListCertificates") + certsResp, scErr := kfClient.ListCertificates(q) + if scErr != nil { + log.Error().Err(scErr).Str("subjectName", s).Msg("failed to list certificates by subject name") + outputError(scErr, true, format) + return scErr + } + if certsResp == nil { + invalidRespErr := fmt.Errorf( + "invalid response returned from Keyfactor Command when calling ListCertificates by subject name '%s'", + s, + ) + log.Error(). + Err(invalidRespErr). + Str("subjectName", s). + Send() + outputError(invalidRespErr, true, format) + return invalidRespErr + } + + log.Debug(). + Str("subjectName", s). + Msg("processing certs to build 'thumbprint' to 'locations map'") + for _, cert := range certsResp { + if rowLookup[cert.Thumbprint] { + log.Debug().Str( + "thumbprint", + cert.Thumbprint, + ).Msg("thumbprint already exists in lookup, skipping") + continue + } + locationsFormatted := "" + for _, loc := range cert.Locations { + locationsFormatted += fmt.Sprintf("%s:%s\n", loc.StoreMachine, loc.StorePath) + log.Debug(). + Str("thumbprint", cert.Thumbprint). + Str("storePath", loc.StorePath). + Str("formattedLocations", locationsFormatted). + Msg("processing location") + } + lineData := []string{ + // "Thumbprint", "SubjectName", "Issuer", "CertID", "Locations", "LastQueriedDate" + cert.Thumbprint, + cert.IssuedCN, + cert.IssuerDN, + fmt.Sprintf("%d", cert.Id), + locationsFormatted, + getCurrentTime(""), + } + log.Debug(). + Str("subjectName", s). + Strs("lineData", lineData). + Msg("adding line data") + csvCertData = append(csvCertData, lineData) + rowLookup[cert.Thumbprint] = true + } + } + log.Info().Int("subjectNames", cns).Msg("lookups by subject-name completed") + } + + var filePath string + if outPath != "" { + filePath = outPath + } else { + filePath = fmt.Sprintf("%s_template.%s", templateType, format) + } + + log.Debug().Str("filePath", filePath).Msg("writing file") + file, err := os.Create(filePath) + defer file.Close() + if err != nil { + log.Error().Err(err).Str("filePath", filePath).Msg("failed to create file") + outputError(err, true, format) + return err + } + + switch format { + case "csv": + log.Debug(). + Str("filePath", filePath). + Str("templateType", templateType). + Msg("writing csv") + writer := csv.NewWriter(file) + var data [][]string + + switch templateType { + case "stores": + log.Debug(). + Str("filePath", filePath). + Str("templateType", templateType). + Msg("writing stores csv") + data = append(data, StoreHeader) + if len(csvStoreData) != 0 { + data = append(data, csvStoreData...) + } + case "certs": + log.Debug(). + Str("filePath", filePath). + Str("templateType", templateType). + Msg("writing certs csv") + data = append(data, CertHeader) + if len(csvCertData) != 0 { + data = append(data, csvCertData...) + } + case "actions": + log.Debug(). + Str("filePath", filePath). + Str("templateType", templateType). + Msg("writing audit csv") + data = append(data, AuditHeader) + } + csvErr := writer.WriteAll(data) + if csvErr != nil { + log.Error().Err(csvErr).Str("filePath", filePath).Msg("failed to write csv") + outputError(csvErr, true, format) + return csvErr + } + case "json": + log.Debug(). + Str("filePath", filePath). + Str("templateType", templateType). + Msg("writing json") + writer := bufio.NewWriter(file) + _, err := writer.WriteString("StoreID,StoreType,StoreMachine,StorePath") + if err != nil { + log.Error().Err(err).Str("filePath", filePath).Msg("failed to write json") + outputError(err, true, format) + return err + } + } + log.Info().Str("filePath", filePath).Msg("template file written") + outputResult(fmt.Sprintf("Template generated at %s", filePath), outputFormat) + return nil + }, + Run: nil, + PostRun: nil, + PostRunE: nil, + PersistentPostRun: nil, + PersistentPostRunE: nil, + FParseErrWhitelist: cobra.FParseErrWhitelist{}, + CompletionOptions: cobra.CompletionOptions{}, + TraverseChildren: false, + Hidden: false, + SilenceErrors: false, + SilenceUsage: false, + DisableFlagParsing: false, + DisableAutoGenTag: false, + DisableFlagsInUseLine: false, + DisableSuggestions: false, + SuggestionsMinimumDistance: 0, + } +) + +func init() { + var ( + stores string + addCerts string + removeCerts string + minCertsInStore int + maxPrivateKeys int + maxLeaves int + tType = tTypeCerts + outPath string + outputFormat string + inputFile string + storeTypes []string + containerNames []string + collections []string + subjectNames []string + ) + + storesCmd.AddCommand(rotCmd) + + // Root of trust `audit` command + rotCmd.AddCommand(rotAuditCmd) + rotAuditCmd.Flags().StringVarP(&stores, "stores", "s", "", "CSV file containing cert stores to enroll into") + rotAuditCmd.Flags().StringVarP( + &addCerts, "add-certs", "a", "", + "CSV file containing cert(s) to enroll into the defined cert stores", + ) + rotAuditCmd.Flags().StringVarP( + &removeCerts, "remove-certs", "r", "", + "CSV file containing cert(s) to remove from the defined cert stores", + ) + rotAuditCmd.Flags().IntVarP( + &minCertsInStore, + "min-certs", + "m", + -1, + "The minimum number of certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", + ) + rotAuditCmd.Flags().IntVarP( + &maxPrivateKeys, + "max-keys", + "k", + -1, + "The max number of private keys that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", + ) + rotAuditCmd.Flags().IntVarP( + &maxLeaves, + "max-leaf-certs", + "l", + -1, + "The max number of non-root-certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", + ) + rotAuditCmd.Flags().BoolP("dry-run", "d", false, "Dry run mode") + rotAuditCmd.Flags().StringVarP( + &outPath, "outpath", "o", "", + "Path to write the audit report file to. If not specified, the file will be written to the current directory.", + ) + + // Root of trust `reconcile` command + rotCmd.AddCommand(rotReconcileCmd) + rotReconcileCmd.Flags().StringVarP(&stores, "stores", "s", "", "CSV file containing cert stores to enroll into") + rotReconcileCmd.Flags().StringVarP( + &addCerts, "add-certs", "a", "", + "CSV file containing cert(s) to enroll into the defined cert stores", + ) + rotReconcileCmd.Flags().StringVarP( + &removeCerts, "remove-certs", "r", "", + "CSV file containing cert(s) to remove from the defined cert stores", + ) + rotReconcileCmd.Flags().IntVarP( + &minCertsInStore, + "min-certs", + "m", + -1, + "The minimum number of certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", + ) + rotReconcileCmd.Flags().IntVarP( + &maxPrivateKeys, + "max-keys", + "k", + -1, + "The max number of private keys that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", + ) + rotReconcileCmd.Flags().IntVarP( + &maxLeaves, + "max-leaf-certs", + "l", + -1, + "The max number of non-root-certs that should be in a store to be considered a 'root' store. If set to `-1` then all stores will be considered.", + ) + rotReconcileCmd.Flags().BoolP("dry-run", "d", false, "Dry run mode") + rotReconcileCmd.Flags().BoolP("import-csv", "v", false, "Import an audit report file in CSV format.") + rotReconcileCmd.Flags().StringVarP( + &inputFile, "input-file", "i", reconcileDefaultFileName, + "Path to a file generated by 'stores rot audit' command.", + ) + rotReconcileCmd.Flags().StringVarP( + &outPath, "outpath", "o", "", + "Path to write the audit report file to. If not specified, the file will be written to the current directory.", + ) + //rotReconcileCmd.MarkFlagsRequiredTogether("add-certs", "stores") + //rotReconcileCmd.MarkFlagsRequiredTogether("remove-certs", "stores") + rotReconcileCmd.MarkFlagsMutuallyExclusive("add-certs", "import-csv") + rotReconcileCmd.MarkFlagsMutuallyExclusive("remove-certs", "import-csv") + rotReconcileCmd.MarkFlagsMutuallyExclusive("stores", "import-csv") + + // Root of trust `generate` command + rotCmd.AddCommand(rotGenStoreTemplateCmd) + rotGenStoreTemplateCmd.Flags().StringVarP( + &outPath, "outpath", "o", "", + "Path to write the template file to. If not specified, the file will be written to the current directory.", + ) + rotGenStoreTemplateCmd.Flags().StringVarP( + &outputFormat, "format", "f", "csv", + "The type of template to generate. Only `csv` is supported at this time.", + ) + rotGenStoreTemplateCmd.Flags().Var( + &tType, "type", + `The type of template to generate. Only "certs|stores|actions" are supported at this time.`, + ) + rotGenStoreTemplateCmd.Flags().StringSliceVar( + &storeTypes, + "store-type", + []string{}, + "Multi value flag. Attempt to pre-populate the stores template with the certificate stores matching specified store types. If not specified, the template will be empty.", + ) + rotGenStoreTemplateCmd.Flags().StringSliceVar( + &containerNames, + "container-name", + []string{}, + "Multi value flag. Attempt to pre-populate the stores template with the certificate stores matching specified container types. If not specified, the template will be empty.", + ) + rotGenStoreTemplateCmd.Flags().StringSliceVar( + &subjectNames, + "cn", + []string{}, + "Subject name(s) to pre-populate the 'certs' template with. If not specified, the template will be empty. Does not work with SANs.", + ) + rotGenStoreTemplateCmd.Flags().StringSliceVar( + &collections, + "collection", + []string{}, + "Certificate collection name(s) to pre-populate the stores template with. If not specified, the template will be empty.", + ) + + rotGenStoreTemplateCmd.RegisterFlagCompletionFunc("type", templateTypeCompletion) + rotGenStoreTemplateCmd.MarkFlagRequired("type") +} From d438dd207c1be9e41615569db6713b1856de3e72 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 14 May 2025 12:26:17 -0700 Subject: [PATCH 16/24] fix(cli): `stores import` don't output create requests in debug logs. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 230318c..3776ea8 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -333,7 +333,7 @@ If you do not wish to include credentials in your CSV file they can be provided log.Debug().Msgf("ContainerId is 0, omitting from request") reqJson.Set(nil, "ContainerId") } - log.Debug().Msgf("Request JSON: %s", reqJson.String()) + //log.Debug().Msgf("Request JSON: %s", reqJson.String()) // parse properties var createStoreReqParameters api.CreateStoreFctArgs @@ -377,7 +377,7 @@ If you do not wish to include credentials in your CSV file they can be provided createStoreReqParameters.Password = passwdParams createStoreReqParameters.Properties = props - log.Debug().Msgf("Request parameters: %v", createStoreReqParameters) + //log.Debug().Msgf("Request parameters: %v", createStoreReqParameters) log.Info().Msgf("Calling Command to create store from row '%d'", idx) res, err := kfClient.CreateStore(&createStoreReqParameters) From 0c05396d446ce20651bb039f070d4819c6535dc4 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 14 May 2025 12:33:41 -0700 Subject: [PATCH 17/24] chore(docs): Update CHANGELOG.md Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11cd075..fd8c668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,10 @@ - `stores import csv`: providing a `Password(/StorePassword)` does not crash CLI. - `stores import csv`: results CSV retains input header ordering. +- `stores import csv`: Handle `BOM` characters in an input CSV file. - `store-types create`: URL encode `-b` parameter when passed. -- `store-types create`: Initialize logger before fetching store-type definitions +- `store-types create`: Initialize logger before fetching store-type definitions. +- `stores rot`: Re-enabled and improved logging. # v1.6.2 From d4381eb2b89c14f5843f589d16effebdc86f58fb Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:56:57 -0700 Subject: [PATCH 18/24] fix(logging): Function enter/exit messages no longer contain a `%s`. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/constants.go | 6 +++--- go.mod | 2 +- go.sum | 4 ++-- pkg/version/version.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/constants.go b/cmd/constants.go index 072a16b..e919bbf 100644 --- a/cmd/constants.go +++ b/cmd/constants.go @@ -30,9 +30,9 @@ const ( FlagGitRef = "git-ref" FlagGitRepo = "repo" FlagFromFile = "from-file" - DebugFuncEnter = "entered: %s" - DebugFuncExit = "exiting: %s" - DebugFuncCall = "calling: %s" + DebugFuncEnter = "entered:" + DebugFuncExit = "exiting:" + DebugFuncCall = "calling:" MinHttpTimeout = 3 EnvStoresImportCSVServerUsername = "KFUTIL_CSV_SERVER_USERNAME" diff --git a/go.mod b/go.mod index 4a62897..45f1f20 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 github.com/Jeffail/gabs v1.4.0 - github.com/Keyfactor/keyfactor-auth-client-go v1.2.0 + github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.1 github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 diff --git a/go.sum b/go.sum index fedff68..c25e54e 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.0 h1:uNSlyOW5Bqpi0nsOGZtOYQzN0vP/h4S4J38jtQes+OI= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.0/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.1 h1:9g6ltxTHfMC65i5VOfVERaATkTHAlF2hfRHztiriQAg= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.1/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 h1:ehk5crxEGVBwkC8yXsoQXcyITTDlgbxMEkANrl1dA2Q= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0/go.mod h1:11WXGG9VVKSV0EPku1IswjHbGGpzHDKqD4pe2vD7vas= github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 h1:DQgb93m3xHZZ0FxWGFS90XI8prwS5fmIGrXNxP2IfHM= diff --git a/pkg/version/version.go b/pkg/version/version.go index 31f7456..433d935 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -15,7 +15,7 @@ package version var ( - VERSION = "1.6.0" - BUILD_DATE = "2024-03-25" + VERSION = "1.7.0" + BUILD_DATE = "2025-05-20" COMMIT = "HEAD" ) From 0ae8be12a69a9f159c629f8e70a9e00c2c0b3e20 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:59:13 -0700 Subject: [PATCH 19/24] feat(logging): Capture imported library logs and redirect to zerolog Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/helpers.go | 22 ++++++++++++++++------ cmd/logging.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ cmd/login.go | 4 +--- cmd/logout.go | 4 +--- cmd/root.go | 9 +++++++-- cmd/rot.go | 6 +++--- cmd/storeTypes.go | 2 +- 7 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 cmd/logging.go diff --git a/cmd/helpers.go b/cmd/helpers.go index 2a4bc1f..b5086c7 100644 --- a/cmd/helpers.go +++ b/cmd/helpers.go @@ -31,8 +31,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" - - stdlog "log" + //stdlog "log" ) func boolToPointer(b bool) *bool { @@ -191,12 +190,23 @@ func informDebug(debugFlag bool) { } func initLogger() { - stdlog.SetOutput(io.Discard) - zerolog.TimeFieldFormat = zerolog.TimeFormatUnix - zerolog.SetGlobalLevel(zerolog.Disabled) // default to disabled - log.Logger = log.With().Caller().Logger() + // Configure zerolog to include caller information + log.Logger = log.With().Caller().Logger().Output( + zerolog.ConsoleWriter{ + Out: os.Stdout, + TimeFormat: time.RFC3339, + FormatCaller: func(caller interface{}) string { + if c, ok := caller.(string); ok { + return c // This will include the full file path and line number + } + return "" + }, + }, + ) log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) + initStdLogger() + } func intToPointer(i int) *int { diff --git a/cmd/logging.go b/cmd/logging.go new file mode 100644 index 0000000..4ecc97d --- /dev/null +++ b/cmd/logging.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "strings" + + "github.com/rs/zerolog/log" +) + +// zerologWriter implements io.Writer and forwards standard log output to zerolog +type zerologWriter struct{} + +func (w zerologWriter) Write(p []byte) (n int, err error) { + // Clean up the log message (remove timestamp, etc.) + msg := string(p) + msg = strings.TrimSpace(msg) + + // Check if it's a debug message + if strings.Contains(msg, "[DEBUG]") { + msg = strings.Replace(msg, "[DEBUG]", "", 1) + log.Debug().Msg(strings.TrimSpace(msg)) + } else if strings.Contains(msg, "[ERROR]") { + msg = strings.Replace(msg, "[ERROR]", "", 1) + log.Error().Msg(strings.TrimSpace(msg)) + } else if strings.Contains(msg, "[INFO]") { + msg = strings.Replace(msg, "[INFO]", "", 1) + log.Info().Msg(strings.TrimSpace(msg)) + + } else if strings.Contains(msg, "[WARN]") { + msg = strings.Replace(msg, "[WARN]", "", 1) + log.Warn().Msg(strings.TrimSpace(msg)) + + } else if strings.Contains(msg, "[FATAL]") { + msg = strings.Replace(msg, "[FATAL]", "", 1) + log.Fatal().Msg(strings.TrimSpace(msg)) + + } else if strings.Contains(msg, "[TRACE]") { + msg = strings.Replace(msg, "[TRACE]", "", 1) + log.Debug().Msg(strings.TrimSpace(msg)) // Converting TRACE to DEBUG for zerolog + } else { + // Default to info level + log.Info().Msg(msg) + } + + return len(p), nil +} diff --git a/cmd/login.go b/cmd/login.go index eea4638..def6282 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -17,8 +17,6 @@ package cmd import ( "bufio" "fmt" - "io" - stdlog "log" "os" "path" "strings" @@ -70,7 +68,7 @@ WARNING: This will write the environmental credentials to disk and will be store if debugErr != nil { return debugErr } - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) informDebug(debugFlag) logGlobals() diff --git a/cmd/logout.go b/cmd/logout.go index f203824..11e1141 100644 --- a/cmd/logout.go +++ b/cmd/logout.go @@ -16,8 +16,6 @@ package cmd import ( "fmt" - "io" - stdlog "log" "os" "github.com/Keyfactor/keyfactor-auth-client-go/auth_providers" @@ -39,7 +37,7 @@ var logoutCmd = &cobra.Command{ if debugErr != nil { return debugErr } - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) informDebug(debugFlag) logGlobals() diff --git a/cmd/root.go b/cmd/root.go index 22ec1cb..2273af3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,7 +17,6 @@ package cmd import ( _ "embed" "fmt" - "io" stdlog "log" "os" "strings" @@ -738,7 +737,7 @@ var RootCmd = &cobra.Command{ // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) err := RootCmd.Execute() if err != nil { os.Exit(1) @@ -881,3 +880,9 @@ func init() { RootCmd.AddCommand(makeDocsCmd) } + +func initStdLogger() { + // Redirect standard library's log to zerolog + stdlog.SetOutput(zerologWriter{}) + stdlog.SetFlags(0) // Remove timestamp from standard logger +} diff --git a/cmd/rot.go b/cmd/rot.go index b8803cb..6c5d6f2 100644 --- a/cmd/rot.go +++ b/cmd/rot.go @@ -631,7 +631,7 @@ kfutil stores rot reconcile --import-csv if debugErr != nil { return debugErr } - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) informDebug(debugFlag) var lookupFailures []string @@ -880,7 +880,7 @@ the utility will first generate an audit report and then execute the add/remove if debugErr != nil { return debugErr } - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) informDebug(debugFlag) var lookupFailures []string @@ -1415,7 +1415,7 @@ the utility will first generate an audit report and then execute the add/remove if debugErr != nil { return debugErr } - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) informDebug(debugFlag) // Authenticate diff --git a/cmd/storeTypes.go b/cmd/storeTypes.go index 4151d91..7cb6154 100644 --- a/cmd/storeTypes.go +++ b/cmd/storeTypes.go @@ -55,7 +55,7 @@ var storesTypesListCmd = &cobra.Command{ if debugErr != nil { return debugErr } - stdlog.SetOutput(io.Discard) + //stdlog.SetOutput(io.Discard) informDebug(debugFlag) // Authenticate From 7a5f6f8d05261a45390f2bcba09e9a3201dc53e1 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:52:45 -0700 Subject: [PATCH 20/24] fix(core): Output auth config params before calling `Authenticate()` Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/login.go | 22 ++++++++++++-- cmd/root.go | 75 ++++++++++++++++++++++++++++++++++++++--------- cmd/rot.go | 2 -- cmd/storeTypes.go | 2 -- go.mod | 2 +- go.sum | 4 +-- 6 files changed, 84 insertions(+), 23 deletions(-) diff --git a/cmd/login.go b/cmd/login.go index def6282..f7d9283 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -235,14 +235,32 @@ WARNING: This will write the environmental credentials to disk and will be store } if authType == "oauth" { - log.Debug().Msg("attempting to authenticate via OAuth") + log.Debug(). + Str("profile", profile). + Str("configFile", configFile). + Str("host", outputServer.Host). + Str("authType", authType). + Str("accessToken", hashSecretValue(kfcOAuth.AccessToken)). + Str("clientID", kfcOAuth.ClientID). + Str("clientSecret", hashSecretValue(kfcOAuth.ClientSecret)). + Str("apiPath", kfcOAuth.CommandAPIPath). + Msg("attempting to authenticate via OAuth") aErr := kfcOAuth.Authenticate() if aErr != nil { log.Error().Err(aErr) return aErr } } else if authType == "basic" { - log.Debug().Msg("attempting to authenticate via Basic Auth") + log.Debug(). + Str("profile", profile). + Str("configFile", configFile). + Str("host", outputServer.Host). + Str("authType", authType). + Str("username", kfcBasicAuth.Username). + Str("domain", kfcBasicAuth.Domain). + Str("password", hashSecretValue(kfcBasicAuth.Password)). + Str("apiPath", kfcBasicAuth.CommandAPIPath). + Msg("attempting to authenticate via Basic Auth") aErr := kfcBasicAuth.Authenticate() if aErr != nil { log.Error().Err(aErr) diff --git a/cmd/root.go b/cmd/root.go index 2273af3..82f0e72 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -134,6 +134,13 @@ func getServerConfigFromEnv() (*auth_providers.Server, error) { apiPath, aOk := os.LookupEnv(auth_providers.EnvKeyfactorAPIPath) clientId, cOk := os.LookupEnv(auth_providers.EnvKeyfactorClientID) clientSecret, csOk := os.LookupEnv(auth_providers.EnvKeyfactorClientSecret) + audience, _ := os.LookupEnv(auth_providers.EnvKeyfactorAuthAudience) + scopesCSV, _ := os.LookupEnv(auth_providers.EnvKeyfactorAuthScopes) + var scopes []string + if scopesCSV != "" { + scopes = strings.Split(scopesCSV, ",") + } + tokenUrl, tOk := os.LookupEnv(auth_providers.EnvKeyfactorAuthTokenURL) skipVerify, svOk := os.LookupEnv(auth_providers.EnvKeyfactorSkipVerify) var skipVerifyBool bool @@ -160,24 +167,44 @@ func getServerConfigFromEnv() (*auth_providers.Server, error) { } if isBasicAuth { - log.Debug(). - Str("username", username). - Str("password", hashSecretValue(password)). - Str("domain", domain). - Str("hostname", hostname). + + log.Debug().Str("hostname", hostname). Str("apiPath", apiPath). Bool("skipVerify", skipVerifyBool). - Msg("call: basicAuthNoParamsConfig.Authenticate()") + Msg("setting up basic auth client base configuration") basicAuthNoParamsConfig.WithCommandHostName(hostname). WithCommandAPIPath(apiPath). WithSkipVerify(skipVerifyBool) - bErr := basicAuthNoParamsConfig. + log.Debug(). + Str("username", username). + Str("password", hashSecretValue(password)). + Str("domain", domain). + Msg("setting up basic auth configuration") + _ = basicAuthNoParamsConfig. WithUsername(username). WithPassword(password). - WithDomain(domain). - Authenticate() - log.Debug().Msg("complete: basicAuthNoParamsConfig.Authenticate()") + WithDomain(domain) + + log.Debug(). + Str("username", basicAuthNoParamsConfig.Username). + Str("password", hashSecretValue(password)). + Str("domain", basicAuthNoParamsConfig.Domain). + Str("hostname", basicAuthNoParamsConfig.CommandHostName). + Str("apiPath", basicAuthNoParamsConfig.CommandAPIPath). + Bool("skipVerify", basicAuthNoParamsConfig.CommandAuthConfig.SkipVerify). + Msg(fmt.Sprintf("%s basicAuthNoParamsConfig.Authenticate()", DebugFuncCall)) + + bErr := basicAuthNoParamsConfig.Authenticate() + log.Debug(). + Str("username", basicAuthNoParamsConfig.Username). + Str("password", hashSecretValue(password)). + Str("domain", basicAuthNoParamsConfig.Domain). + Str("hostname", basicAuthNoParamsConfig.CommandHostName). + Str("apiPath", basicAuthNoParamsConfig.CommandAPIPath). + Bool("skipVerify", basicAuthNoParamsConfig.CommandAuthConfig.SkipVerify). + Msg("complete: basicAuthNoParamsConfig.Authenticate()") + if bErr != nil { log.Error().Err(bErr).Msg("unable to authenticate with provided credentials") return nil, bErr @@ -186,16 +213,36 @@ func getServerConfigFromEnv() (*auth_providers.Server, error) { return basicAuthNoParamsConfig.GetServerConfig(), nil } else if isOAuth { log.Debug(). - Str("clientId", clientId). - Str("clientSecret", hashSecretValue(clientSecret)). - Str("tokenUrl", tokenUrl). Str("hostname", hostname). Str("apiPath", apiPath). Bool("skipVerify", skipVerifyBool). - Msg("call: oAuthNoParamsConfig.Authenticate()") + Msg("setting up oAuth client base configuration") _ = oAuthNoParamsConfig.CommandAuthConfig.WithCommandHostName(hostname). WithCommandAPIPath(apiPath). WithSkipVerify(skipVerifyBool) + + log.Debug(). + Str("clientId", clientId). + Str("clientSecret", hashSecretValue(clientSecret)). + Str("tokenUrl", tokenUrl). + Str("audience", audience). + Strs("scopes", scopes). + Msg("setting up oAuth configuration") + _ = oAuthNoParamsConfig.WithClientId(clientId). + WithClientSecret(clientSecret). + WithTokenUrl(tokenUrl). + WithAudience(audience). + WithScopes(scopes) + + log.Debug(). + Str("clientId", oAuthNoParamsConfig.ClientID). + Str("clientSecret", hashSecretValue(oAuthNoParamsConfig.ClientSecret)). + Str("tokenUrl", oAuthNoParamsConfig.TokenURL). + Str("hostname", oAuthNoParamsConfig.CommandHostName). + Str("apiPath", oAuthNoParamsConfig.CommandAPIPath). + Bool("skipVerify", oAuthNoParamsConfig.SkipVerify). + Str("caCert", oAuthNoParamsConfig.CommandCACert). + Msg(fmt.Sprintf("%s oAuthNoParamsConfig.Authenticate()", DebugFuncCall)) oErr := oAuthNoParamsConfig.Authenticate() log.Debug().Msg("complete: oAuthNoParamsConfig.Authenticate()") if oErr != nil { diff --git a/cmd/rot.go b/cmd/rot.go index 6c5d6f2..f47dc32 100644 --- a/cmd/rot.go +++ b/cmd/rot.go @@ -20,8 +20,6 @@ import ( "encoding/json" "errors" "fmt" - "io" - stdlog "log" "os" "strconv" "strings" diff --git a/cmd/storeTypes.go b/cmd/storeTypes.go index 7cb6154..ca2be2b 100644 --- a/cmd/storeTypes.go +++ b/cmd/storeTypes.go @@ -26,8 +26,6 @@ import ( "strings" "time" - stdlog "log" - "github.com/AlecAivazis/survey/v2" "github.com/Keyfactor/keyfactor-go-client/v3/api" "github.com/rs/zerolog/log" diff --git a/go.mod b/go.mod index 45f1f20..a563ab1 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 github.com/Jeffail/gabs v1.4.0 - github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.1 + github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.2 github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 diff --git a/go.sum b/go.sum index c25e54e..24f10a1 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.1 h1:9g6ltxTHfMC65i5VOfVERaATkTHAlF2hfRHztiriQAg= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.1/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.2 h1:iYl9uaj/YB/5AE/WFl4FP5FP3Cu5I01r+jXNES018vw= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.2/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 h1:ehk5crxEGVBwkC8yXsoQXcyITTDlgbxMEkANrl1dA2Q= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0/go.mod h1:11WXGG9VVKSV0EPku1IswjHbGGpzHDKqD4pe2vD7vas= github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 h1:DQgb93m3xHZZ0FxWGFS90XI8prwS5fmIGrXNxP2IfHM= From da67c27db50e16c747bf1d502b92624db01e1246 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Fri, 6 Jun 2025 11:41:10 -0700 Subject: [PATCH 21/24] chore(deps): Bump go version to `1.24` and update all direct imports Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/logging.go | 2 +- go.mod | 24 ++++++++++++------------ go.sum | 44 ++++++++++++++++++++++---------------------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/cmd/logging.go b/cmd/logging.go index 4ecc97d..45b3605 100644 --- a/cmd/logging.go +++ b/cmd/logging.go @@ -35,7 +35,7 @@ func (w zerologWriter) Write(p []byte) (n int, err error) { } else if strings.Contains(msg, "[TRACE]") { msg = strings.Replace(msg, "[TRACE]", "", 1) - log.Debug().Msg(strings.TrimSpace(msg)) // Converting TRACE to DEBUG for zerolog + log.Trace().Msg(strings.TrimSpace(msg)) } else { // Default to info level log.Info().Msg(msg) diff --git a/go.mod b/go.mod index a563ab1..2361190 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module kfutil -go 1.23.0 +go 1.24.0 -toolchain go1.24.2 +toolchain go1.24.3 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 github.com/Jeffail/gabs v1.4.0 - github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.2 + github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.8 github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 @@ -22,16 +22,16 @@ require ( github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.37.0 - golang.org/x/term v0.31.0 + golang.org/x/crypto v0.39.0 + golang.org/x/term v0.32.0 gopkg.in/yaml.v3 v3.0.1 //github.com/google/go-cmp/cmp v0.5.9 ) require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -50,9 +50,9 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spbsoluble/go-pkcs12 v0.3.3 // indirect go.mozilla.org/pkcs7 v0.9.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/oauth2 v0.25.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/net v0.41.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.26.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 24f10a1..ed22252 100644 --- a/go.sum +++ b/go.sum @@ -2,24 +2,24 @@ github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkk github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.0 h1:WLUIpeyv04H0RCcQHaA4TNoyrQ39Ox7V+re+iaqzTe0= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.0/go.mod h1:hd8hTTIY3VmUVPRHNH7GVCHO3SHgXkJKZHReby/bnUQ= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 h1:eXnN9kaS8TiDwXjoie3hMRLuwdUBUMW9KRgOqB3mCaw= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0/go.mod h1:XIpam8wumeZ5rVMuhdDQLMfIPDf1WO3IzrCRO3e3e3o= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1 h1:mrkDCdkMsD4l9wjFGhofFHFrV43Y3c53RSLKOCJ5+Ow= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1/go.mod h1:hPv41DbqMmnxcGralanA/kVlfdH5jv3T4LxGku2E1BY= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.2 h1:iYl9uaj/YB/5AE/WFl4FP5FP3Cu5I01r+jXNES018vw= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.2/go.mod h1:7htRcBIWn+X4fI5jaYBALSYwP84H/djN7d8y3n0ZDQ0= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.8 h1:HXk2hLoBNlb8VBuytKjzoyCUHrPkfCA/3bd3KIKM8o8= +github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.8/go.mod h1:RoKxcp/xkLiPqXkyAldPaMbNde9P1tt25Ztrd7kyW+M= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 h1:ehk5crxEGVBwkC8yXsoQXcyITTDlgbxMEkANrl1dA2Q= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0/go.mod h1:11WXGG9VVKSV0EPku1IswjHbGGpzHDKqD4pe2vD7vas= github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 h1:DQgb93m3xHZZ0FxWGFS90XI8prwS5fmIGrXNxP2IfHM= @@ -93,8 +93,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= -github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= @@ -118,16 +118,16 @@ go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI= go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -145,18 +145,18 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From 2b122c995afda7f0803a4b6c6e7c304ab8247caf Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Tue, 17 Jun 2025 10:41:26 -0700 Subject: [PATCH 22/24] chore(docs): Add docs for `stores import csv` inventory headers Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 12 ++++++++++++ docs/kfutil.md | 2 +- docs/kfutil_completion.md | 2 +- docs/kfutil_completion_bash.md | 2 +- docs/kfutil_completion_fish.md | 2 +- docs/kfutil_completion_powershell.md | 2 +- docs/kfutil_completion_zsh.md | 2 +- docs/kfutil_containers.md | 2 +- docs/kfutil_containers_get.md | 2 +- docs/kfutil_containers_list.md | 2 +- docs/kfutil_export.md | 2 +- docs/kfutil_helm.md | 2 +- docs/kfutil_helm_uo.md | 2 +- docs/kfutil_import.md | 2 +- docs/kfutil_login.md | 2 +- docs/kfutil_logout.md | 2 +- docs/kfutil_orchs.md | 2 +- docs/kfutil_orchs_approve.md | 2 +- docs/kfutil_orchs_disapprove.md | 2 +- docs/kfutil_orchs_ext.md | 2 +- docs/kfutil_orchs_get.md | 2 +- docs/kfutil_orchs_list.md | 2 +- docs/kfutil_orchs_logs.md | 2 +- docs/kfutil_orchs_reset.md | 2 +- docs/kfutil_pam.md | 2 +- docs/kfutil_pam_create.md | 2 +- docs/kfutil_pam_delete.md | 2 +- docs/kfutil_pam_get.md | 2 +- docs/kfutil_pam_list.md | 2 +- docs/kfutil_pam_types-create.md | 2 +- docs/kfutil_pam_types-list.md | 2 +- docs/kfutil_pam_update.md | 2 +- docs/kfutil_status.md | 2 +- docs/kfutil_store-types.md | 2 +- docs/kfutil_store-types_create.md | 2 +- docs/kfutil_store-types_delete.md | 2 +- docs/kfutil_store-types_get.md | 2 +- docs/kfutil_store-types_list.md | 2 +- docs/kfutil_store-types_templates-fetch.md | 2 +- docs/kfutil_stores.md | 3 ++- docs/kfutil_stores_delete.md | 2 +- docs/kfutil_stores_export.md | 2 +- docs/kfutil_stores_get.md | 2 +- docs/kfutil_stores_import.md | 2 +- docs/kfutil_stores_import_csv.md | 15 +++++++++++++-- docs/kfutil_stores_import_generate-template.md | 2 +- docs/kfutil_stores_inventory.md | 2 +- docs/kfutil_stores_inventory_add.md | 2 +- docs/kfutil_stores_inventory_remove.md | 2 +- docs/kfutil_stores_inventory_show.md | 2 +- docs/kfutil_stores_list.md | 2 +- docs/kfutil_stores_rot.md | 7 +++++-- docs/kfutil_stores_rot_audit.md | 7 +++++-- docs/kfutil_stores_rot_generate-template.md | 7 +++++-- docs/kfutil_stores_rot_reconcile.md | 7 +++++-- docs/kfutil_version.md | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- main.go | 16 +++++++++------- 59 files changed, 111 insertions(+), 73 deletions(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index 3776ea8..a4c101f 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -123,12 +123,24 @@ Required Flags: ##### In the CSV file: +###### Credential Fields + | Header | Description | | --- | --- | | Properties.ServerUsername | This is equivalent to the 'ServerUsername' field in the Command Certificate Store UI. | | Properties.ServerPassword | This is equivalent to the 'ServerPassword' field in the Command Certificate Store UI. | | Password | This is equivalent to the 'StorePassword' field in the Command Certificate Store UI. | +###### Inventory Schedule Fields + +| Header | Description | +| --- | --- | +| InventorySchedule.Immediate | Boolean value, set to "TRUE" to schedule immediate inventory | +| InventorySchedule.Interval.Minutes | The timeframe in which to periodically inventory int number/integer value. Ex.120 for 2 hours. | +| InventorySchedule.Daily.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | +| InventorySchedule.Weekly.Days | TBD | +| InventorySchedule.Weekly.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | + ##### Outside CSV file: If you do not wish to include credentials in your CSV file they can be provided one of three ways: - via the --server-username --server-password and --store-password flags diff --git a/docs/kfutil.md b/docs/kfutil.md index d7e91aa..d861138 100644 --- a/docs/kfutil.md +++ b/docs/kfutil.md @@ -46,4 +46,4 @@ A CLI wrapper around the Keyfactor Platform API. * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. * [kfutil version](kfutil_version.md) - Shows version of kfutil -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_completion.md b/docs/kfutil_completion.md index bc2b115..e22e82b 100644 --- a/docs/kfutil_completion.md +++ b/docs/kfutil_completion.md @@ -45,4 +45,4 @@ See each sub-command's help for details on how to use the generated script. * [kfutil completion powershell](kfutil_completion_powershell.md) - Generate the autocompletion script for powershell * [kfutil completion zsh](kfutil_completion_zsh.md) - Generate the autocompletion script for zsh -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_completion_bash.md b/docs/kfutil_completion_bash.md index f3e095a..e002d6d 100644 --- a/docs/kfutil_completion_bash.md +++ b/docs/kfutil_completion_bash.md @@ -64,4 +64,4 @@ kfutil completion bash * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_completion_fish.md b/docs/kfutil_completion_fish.md index f92d133..fd50972 100644 --- a/docs/kfutil_completion_fish.md +++ b/docs/kfutil_completion_fish.md @@ -55,4 +55,4 @@ kfutil completion fish [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_completion_powershell.md b/docs/kfutil_completion_powershell.md index 24c9894..6ae54ea 100644 --- a/docs/kfutil_completion_powershell.md +++ b/docs/kfutil_completion_powershell.md @@ -52,4 +52,4 @@ kfutil completion powershell [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_completion_zsh.md b/docs/kfutil_completion_zsh.md index fb3ca06..b3a0672 100644 --- a/docs/kfutil_completion_zsh.md +++ b/docs/kfutil_completion_zsh.md @@ -66,4 +66,4 @@ kfutil completion zsh [flags] * [kfutil completion](kfutil_completion.md) - Generate the autocompletion script for the specified shell -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_containers.md b/docs/kfutil_containers.md index 5af7d38..667a635 100644 --- a/docs/kfutil_containers.md +++ b/docs/kfutil_containers.md @@ -41,4 +41,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil containers get](kfutil_containers_get.md) - Get certificate store container by ID or name. * [kfutil containers list](kfutil_containers_list.md) - List certificate store containers. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_containers_get.md b/docs/kfutil_containers_get.md index 96389a4..54bcb25 100644 --- a/docs/kfutil_containers_get.md +++ b/docs/kfutil_containers_get.md @@ -44,4 +44,4 @@ kfutil containers get [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_containers_list.md b/docs/kfutil_containers_list.md index ca31b47..496661b 100644 --- a/docs/kfutil_containers_list.md +++ b/docs/kfutil_containers_list.md @@ -43,4 +43,4 @@ kfutil containers list [flags] * [kfutil containers](kfutil_containers.md) - Keyfactor certificate store container API and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_export.md b/docs/kfutil_export.md index 992468c..7b255a5 100644 --- a/docs/kfutil_export.md +++ b/docs/kfutil_export.md @@ -55,4 +55,4 @@ kfutil export [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_helm.md b/docs/kfutil_helm.md index f20eab0..c0facc8 100644 --- a/docs/kfutil_helm.md +++ b/docs/kfutil_helm.md @@ -46,4 +46,4 @@ kubectl helm uo | helm install -f - keyfactor-universal-orchestrator keyfactor/k * [kfutil](kfutil.md) - Keyfactor CLI utilities * [kfutil helm uo](kfutil_helm_uo.md) - Configure the Keyfactor Universal Orchestrator Helm Chart -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_helm_uo.md b/docs/kfutil_helm_uo.md index 9e1ef98..a5e2833 100644 --- a/docs/kfutil_helm_uo.md +++ b/docs/kfutil_helm_uo.md @@ -50,4 +50,4 @@ kfutil helm uo [-t ] [-o ] [-f ] [-e -e @,@ -o ./app/extension * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_orchs_get.md b/docs/kfutil_orchs_get.md index 35c428a..245e10a 100644 --- a/docs/kfutil_orchs_get.md +++ b/docs/kfutil_orchs_get.md @@ -44,4 +44,4 @@ kfutil orchs get [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_orchs_list.md b/docs/kfutil_orchs_list.md index 4a19313..bf55a9a 100644 --- a/docs/kfutil_orchs_list.md +++ b/docs/kfutil_orchs_list.md @@ -43,4 +43,4 @@ kfutil orchs list [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_orchs_logs.md b/docs/kfutil_orchs_logs.md index 65ab207..14d971e 100644 --- a/docs/kfutil_orchs_logs.md +++ b/docs/kfutil_orchs_logs.md @@ -44,4 +44,4 @@ kfutil orchs logs [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_orchs_reset.md b/docs/kfutil_orchs_reset.md index dcd1384..032349a 100644 --- a/docs/kfutil_orchs_reset.md +++ b/docs/kfutil_orchs_reset.md @@ -44,4 +44,4 @@ kfutil orchs reset [flags] * [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam.md b/docs/kfutil_pam.md index 5399a80..6d22a6d 100644 --- a/docs/kfutil_pam.md +++ b/docs/kfutil_pam.md @@ -48,4 +48,4 @@ programmatically create, delete, edit, and list PAM Providers. * [kfutil pam types-list](kfutil_pam_types-list.md) - Returns a list of all available PAM provider types. * [kfutil pam update](kfutil_pam_update.md) - Updates an existing PAM Provider, currently only supported from file. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_create.md b/docs/kfutil_pam_create.md index 35eaf32..1fd5f60 100644 --- a/docs/kfutil_pam_create.md +++ b/docs/kfutil_pam_create.md @@ -44,4 +44,4 @@ kfutil pam create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_delete.md b/docs/kfutil_pam_delete.md index 594f3d7..28c16e1 100644 --- a/docs/kfutil_pam_delete.md +++ b/docs/kfutil_pam_delete.md @@ -44,4 +44,4 @@ kfutil pam delete [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_get.md b/docs/kfutil_pam_get.md index 3bb7c23..afc07d7 100644 --- a/docs/kfutil_pam_get.md +++ b/docs/kfutil_pam_get.md @@ -44,4 +44,4 @@ kfutil pam get [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_list.md b/docs/kfutil_pam_list.md index 3f58dc6..217b568 100644 --- a/docs/kfutil_pam_list.md +++ b/docs/kfutil_pam_list.md @@ -43,4 +43,4 @@ kfutil pam list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_types-create.md b/docs/kfutil_pam_types-create.md index f8dcd92..9c0e244 100644 --- a/docs/kfutil_pam_types-create.md +++ b/docs/kfutil_pam_types-create.md @@ -51,4 +51,4 @@ kfutil pam types-create [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_types-list.md b/docs/kfutil_pam_types-list.md index 01314a7..8fe920d 100644 --- a/docs/kfutil_pam_types-list.md +++ b/docs/kfutil_pam_types-list.md @@ -43,4 +43,4 @@ kfutil pam types-list [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_pam_update.md b/docs/kfutil_pam_update.md index 6c78b7d..35ab4bb 100644 --- a/docs/kfutil_pam_update.md +++ b/docs/kfutil_pam_update.md @@ -44,4 +44,4 @@ kfutil pam update [flags] * [kfutil pam](kfutil_pam.md) - Keyfactor PAM Provider APIs. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_status.md b/docs/kfutil_status.md index 20ce403..193d051 100644 --- a/docs/kfutil_status.md +++ b/docs/kfutil_status.md @@ -43,4 +43,4 @@ kfutil status [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_store-types.md b/docs/kfutil_store-types.md index 7b35c1b..05c3cac 100644 --- a/docs/kfutil_store-types.md +++ b/docs/kfutil_store-types.md @@ -44,4 +44,4 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s * [kfutil store-types list](kfutil_store-types_list.md) - List certificate store types. * [kfutil store-types templates-fetch](kfutil_store-types_templates-fetch.md) - Fetches store type templates from Keyfactor's Github. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_store-types_create.md b/docs/kfutil_store-types_create.md index e8564f6..ef02796 100644 --- a/docs/kfutil_store-types_create.md +++ b/docs/kfutil_store-types_create.md @@ -49,4 +49,4 @@ kfutil store-types create [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_store-types_delete.md b/docs/kfutil_store-types_delete.md index 67f5920..a8b9500 100644 --- a/docs/kfutil_store-types_delete.md +++ b/docs/kfutil_store-types_delete.md @@ -47,4 +47,4 @@ kfutil store-types delete [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_store-types_get.md b/docs/kfutil_store-types_get.md index 756f0a8..9a249cc 100644 --- a/docs/kfutil_store-types_get.md +++ b/docs/kfutil_store-types_get.md @@ -48,4 +48,4 @@ kfutil store-types get [-i | -n ] [-b * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_store-types_list.md b/docs/kfutil_store-types_list.md index a132026..4fb07e6 100644 --- a/docs/kfutil_store-types_list.md +++ b/docs/kfutil_store-types_list.md @@ -43,4 +43,4 @@ kfutil store-types list [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_store-types_templates-fetch.md b/docs/kfutil_store-types_templates-fetch.md index d5d4385..9df5d69 100644 --- a/docs/kfutil_store-types_templates-fetch.md +++ b/docs/kfutil_store-types_templates-fetch.md @@ -45,4 +45,4 @@ kfutil store-types templates-fetch [flags] * [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores.md b/docs/kfutil_stores.md index e10e96e..c15f5c2 100644 --- a/docs/kfutil_stores.md +++ b/docs/kfutil_stores.md @@ -45,5 +45,6 @@ A collections of APIs and utilities for interacting with Keyfactor certificate s in Keyfactor Command. * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management * [kfutil stores list](kfutil_stores_list.md) - List certificate stores. +* [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_delete.md b/docs/kfutil_stores_delete.md index 9f934f9..c8f68b9 100644 --- a/docs/kfutil_stores_delete.md +++ b/docs/kfutil_stores_delete.md @@ -46,4 +46,4 @@ kfutil stores delete [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_export.md b/docs/kfutil_stores_export.md index 0b8557e..85fac2a 100644 --- a/docs/kfutil_stores_export.md +++ b/docs/kfutil_stores_export.md @@ -47,4 +47,4 @@ kfutil stores export [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_get.md b/docs/kfutil_stores_get.md index 5545c0b..f2966da 100644 --- a/docs/kfutil_stores_get.md +++ b/docs/kfutil_stores_get.md @@ -44,4 +44,4 @@ kfutil stores get [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_import.md b/docs/kfutil_stores_import.md index 337505f..6144088 100644 --- a/docs/kfutil_stores_import.md +++ b/docs/kfutil_stores_import.md @@ -41,4 +41,4 @@ Tools for generating import templates and importing certificate stores * [kfutil stores import csv](kfutil_stores_import_csv.md) - Create certificate stores from CSV file. * [kfutil stores import generate-template](kfutil_stores_import_generate-template.md) - For generating a CSV template with headers for bulk store creation. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_import_csv.md b/docs/kfutil_stores_import_csv.md index 908080c..3bfd01c 100644 --- a/docs/kfutil_stores_import_csv.md +++ b/docs/kfutil_stores_import_csv.md @@ -8,7 +8,6 @@ Will parse a CSV file and attempt to create a certificate store for each row wit Any errors encountered will be logged to the _results.csv file, under the 'Errors' column. Required Flags: - - '--store-type-name' OR '--store-type-id' - '--file' is the path to the file to be imported. @@ -16,12 +15,24 @@ Required Flags: ##### In the CSV file: +###### Credential Fields + | Header | Description | |---------------------------|---------------------------------------------------------------------------------------| | Properties.ServerUsername | This is equivalent to the 'ServerUsername' field in the Command Certificate Store UI. | | Properties.ServerPassword | This is equivalent to the 'ServerPassword' field in the Command Certificate Store UI. | | Password | This is equivalent to the 'StorePassword' field in the Command Certificate Store UI. | +###### Inventory Schedule Fields + +| Header | Description | +|------------------------------------|------------------------------------------------------------------------------------------------| +| InventorySchedule.Immediate | Boolean value, set to "TRUE" to schedule immediate inventory | +| InventorySchedule.Interval.Minutes | The timeframe in which to periodically inventory int number/integer value. Ex.120 for 2 hours. | +| InventorySchedule.Daily.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | +| InventorySchedule.Weekly.Days | TBD | +| InventorySchedule.Weekly.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | + ##### Outside CSV file: If you do not wish to include credentials in your CSV file they can be provided one of three ways: - via the --server-username --server-password and --store-password flags @@ -75,4 +86,4 @@ kfutil stores import csv --file --store-type-id --store-t * [kfutil stores import](kfutil_stores_import.md) - Import a file with certificate store definitions and create them in Keyfactor Command. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_inventory.md b/docs/kfutil_stores_inventory.md index 3d1256a..bdfee73 100644 --- a/docs/kfutil_stores_inventory.md +++ b/docs/kfutil_stores_inventory.md @@ -42,4 +42,4 @@ Commands related to certificate store inventory management * [kfutil stores inventory remove](kfutil_stores_inventory_remove.md) - Removes a certificate from the certificate store inventory. * [kfutil stores inventory show](kfutil_stores_inventory_show.md) - Show the inventory of a certificate store. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_inventory_add.md b/docs/kfutil_stores_inventory_add.md index 9e9b392..3f2c38c 100644 --- a/docs/kfutil_stores_inventory_add.md +++ b/docs/kfutil_stores_inventory_add.md @@ -57,4 +57,4 @@ kfutil stores inventory add [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_inventory_remove.md b/docs/kfutil_stores_inventory_remove.md index 90d2abc..06719df 100644 --- a/docs/kfutil_stores_inventory_remove.md +++ b/docs/kfutil_stores_inventory_remove.md @@ -53,4 +53,4 @@ kfutil stores inventory remove [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_inventory_show.md b/docs/kfutil_stores_inventory_show.md index 5f5efbf..e6d6bc2 100644 --- a/docs/kfutil_stores_inventory_show.md +++ b/docs/kfutil_stores_inventory_show.md @@ -47,4 +47,4 @@ kfutil stores inventory show [flags] * [kfutil stores inventory](kfutil_stores_inventory.md) - Commands related to certificate store inventory management -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_list.md b/docs/kfutil_stores_list.md index 20deef0..9557d62 100644 --- a/docs/kfutil_stores_list.md +++ b/docs/kfutil_stores_list.md @@ -43,4 +43,4 @@ kfutil stores list [flags] * [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities. -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_rot.md b/docs/kfutil_stores_rot.md index 715ea0c..d47038c 100644 --- a/docs/kfutil_stores_rot.md +++ b/docs/kfutil_stores_rot.md @@ -30,17 +30,20 @@ kfutil stores rot reconcile --import-csv --api-path string API Path to use for authenticating to Keyfactor Command. (default is KeyfactorAPI) (default "KeyfactorAPI") --auth-provider-profile string The profile to use defined in the securely stored config. If not specified the config named 'default' will be used if it exists. (default "default") --auth-provider-type string Provider type choices: (azid) + --client-id string OAuth2 client-id to use for authenticating to Keyfactor Command. + --client-secret string OAuth2 client-secret to use for authenticating to Keyfactor Command. --config string Full path to config file in JSON format. (default is $HOME/.keyfactor/command_config.json) --debug Enable debugFlag logging. --domain string Domain to use for authenticating to Keyfactor Command. --exp Enable expEnabled features. (USE AT YOUR OWN RISK, these features are not supported and may change or be removed at any time.) --format text How to format the CLI output. Currently only text is supported. (default "text") --hostname string Hostname to use for authenticating to Keyfactor Command. - --log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.) --no-prompt Do not prompt for any user input and assume defaults or environmental variables are set. --offline Will not attempt to connect to GitHub for latest release information and resources. --password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text. --profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists. + --skip-tls-verify Disable TLS verification for API requests to Keyfactor Command. + --token-url string OAuth2 token endpoint full URL to use for authenticating to Keyfactor Command. --username string Username to use for authenticating to Keyfactor Command. ``` @@ -51,4 +54,4 @@ kfutil stores rot reconcile --import-csv * [kfutil stores rot generate-template](kfutil_stores_rot_generate-template.md) - For generating Root Of Trust template(s) * [kfutil stores rot reconcile](kfutil_stores_rot_reconcile.md) - Reconcile either takes in or will generate an audit report and then add/remove certs as needed. -###### Auto generated on 8-Sep-2024 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_rot_audit.md b/docs/kfutil_stores_rot_audit.md index b9b8a3e..02af86c 100644 --- a/docs/kfutil_stores_rot_audit.md +++ b/docs/kfutil_stores_rot_audit.md @@ -30,17 +30,20 @@ kfutil stores rot audit [flags] --api-path string API Path to use for authenticating to Keyfactor Command. (default is KeyfactorAPI) (default "KeyfactorAPI") --auth-provider-profile string The profile to use defined in the securely stored config. If not specified the config named 'default' will be used if it exists. (default "default") --auth-provider-type string Provider type choices: (azid) + --client-id string OAuth2 client-id to use for authenticating to Keyfactor Command. + --client-secret string OAuth2 client-secret to use for authenticating to Keyfactor Command. --config string Full path to config file in JSON format. (default is $HOME/.keyfactor/command_config.json) --debug Enable debugFlag logging. --domain string Domain to use for authenticating to Keyfactor Command. --exp Enable expEnabled features. (USE AT YOUR OWN RISK, these features are not supported and may change or be removed at any time.) --format text How to format the CLI output. Currently only text is supported. (default "text") --hostname string Hostname to use for authenticating to Keyfactor Command. - --log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.) --no-prompt Do not prompt for any user input and assume defaults or environmental variables are set. --offline Will not attempt to connect to GitHub for latest release information and resources. --password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text. --profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists. + --skip-tls-verify Disable TLS verification for API requests to Keyfactor Command. + --token-url string OAuth2 token endpoint full URL to use for authenticating to Keyfactor Command. --username string Username to use for authenticating to Keyfactor Command. ``` @@ -48,4 +51,4 @@ kfutil stores rot audit [flags] * [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated on 8-Sep-2024 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_rot_generate-template.md b/docs/kfutil_stores_rot_generate-template.md index 63b5d0f..92f6180 100644 --- a/docs/kfutil_stores_rot_generate-template.md +++ b/docs/kfutil_stores_rot_generate-template.md @@ -29,16 +29,19 @@ kfutil stores rot generate-template [flags] --api-path string API Path to use for authenticating to Keyfactor Command. (default is KeyfactorAPI) (default "KeyfactorAPI") --auth-provider-profile string The profile to use defined in the securely stored config. If not specified the config named 'default' will be used if it exists. (default "default") --auth-provider-type string Provider type choices: (azid) + --client-id string OAuth2 client-id to use for authenticating to Keyfactor Command. + --client-secret string OAuth2 client-secret to use for authenticating to Keyfactor Command. --config string Full path to config file in JSON format. (default is $HOME/.keyfactor/command_config.json) --debug Enable debugFlag logging. --domain string Domain to use for authenticating to Keyfactor Command. --exp Enable expEnabled features. (USE AT YOUR OWN RISK, these features are not supported and may change or be removed at any time.) --hostname string Hostname to use for authenticating to Keyfactor Command. - --log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.) --no-prompt Do not prompt for any user input and assume defaults or environmental variables are set. --offline Will not attempt to connect to GitHub for latest release information and resources. --password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text. --profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists. + --skip-tls-verify Disable TLS verification for API requests to Keyfactor Command. + --token-url string OAuth2 token endpoint full URL to use for authenticating to Keyfactor Command. --username string Username to use for authenticating to Keyfactor Command. ``` @@ -46,4 +49,4 @@ kfutil stores rot generate-template [flags] * [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated on 8-Sep-2024 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_stores_rot_reconcile.md b/docs/kfutil_stores_rot_reconcile.md index a861b91..b50170d 100644 --- a/docs/kfutil_stores_rot_reconcile.md +++ b/docs/kfutil_stores_rot_reconcile.md @@ -35,17 +35,20 @@ kfutil stores rot reconcile [flags] --api-path string API Path to use for authenticating to Keyfactor Command. (default is KeyfactorAPI) (default "KeyfactorAPI") --auth-provider-profile string The profile to use defined in the securely stored config. If not specified the config named 'default' will be used if it exists. (default "default") --auth-provider-type string Provider type choices: (azid) + --client-id string OAuth2 client-id to use for authenticating to Keyfactor Command. + --client-secret string OAuth2 client-secret to use for authenticating to Keyfactor Command. --config string Full path to config file in JSON format. (default is $HOME/.keyfactor/command_config.json) --debug Enable debugFlag logging. --domain string Domain to use for authenticating to Keyfactor Command. --exp Enable expEnabled features. (USE AT YOUR OWN RISK, these features are not supported and may change or be removed at any time.) --format text How to format the CLI output. Currently only text is supported. (default "text") --hostname string Hostname to use for authenticating to Keyfactor Command. - --log-insecure Log insecure API requests. (USE AT YOUR OWN RISK, this WILL log sensitive information to the console.) --no-prompt Do not prompt for any user input and assume defaults or environmental variables are set. --offline Will not attempt to connect to GitHub for latest release information and resources. --password string Password to use for authenticating to Keyfactor Command. WARNING: Remember to delete your console history if providing kfcPassword here in plain text. --profile string Use a specific profile from your config file. If not specified the config named 'default' will be used if it exists. + --skip-tls-verify Disable TLS verification for API requests to Keyfactor Command. + --token-url string OAuth2 token endpoint full URL to use for authenticating to Keyfactor Command. --username string Username to use for authenticating to Keyfactor Command. ``` @@ -53,4 +56,4 @@ kfutil stores rot reconcile [flags] * [kfutil stores rot](kfutil_stores_rot.md) - Root of trust utility -###### Auto generated on 8-Sep-2024 +###### Auto generated on 17-Jun-2025 diff --git a/docs/kfutil_version.md b/docs/kfutil_version.md index 36d6180..43447ad 100644 --- a/docs/kfutil_version.md +++ b/docs/kfutil_version.md @@ -43,4 +43,4 @@ kfutil version [flags] * [kfutil](kfutil.md) - Keyfactor CLI utilities -###### Auto generated by spf13/cobra on 29-Apr-2025 +###### Auto generated on 17-Jun-2025 diff --git a/go.mod b/go.mod index 2361190..a424d59 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ toolchain go1.24.3 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Jeffail/gabs v1.4.0 - github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.8 + github.com/Keyfactor/keyfactor-auth-client-go v1.3.0 github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 diff --git a/go.sum b/go.sum index ed22252..ea69bb4 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkk github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 h1:j8BorDEigD8UFOSZQiSqAMOOleyQOOQPnUAwV+Ls1gA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= @@ -18,8 +18,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJ github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.8 h1:HXk2hLoBNlb8VBuytKjzoyCUHrPkfCA/3bd3KIKM8o8= -github.com/Keyfactor/keyfactor-auth-client-go v1.2.1-rc.8/go.mod h1:RoKxcp/xkLiPqXkyAldPaMbNde9P1tt25Ztrd7kyW+M= +github.com/Keyfactor/keyfactor-auth-client-go v1.3.0 h1:otC213b6CYzqeN9b3CRlH1Qj1hTFIN5nqPA8gTlHdLg= +github.com/Keyfactor/keyfactor-auth-client-go v1.3.0/go.mod h1:97vCisBNkdCK0l2TuvOSdjlpvQa4+GHsMut1UTyv1jo= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0 h1:ehk5crxEGVBwkC8yXsoQXcyITTDlgbxMEkANrl1dA2Q= github.com/Keyfactor/keyfactor-go-client-sdk/v2 v2.0.0/go.mod h1:11WXGG9VVKSV0EPku1IswjHbGGpzHDKqD4pe2vD7vas= github.com/Keyfactor/keyfactor-go-client/v3 v3.1.0 h1:DQgb93m3xHZZ0FxWGFS90XI8prwS5fmIGrXNxP2IfHM= diff --git a/main.go b/main.go index 15e0228..68cf1d6 100644 --- a/main.go +++ b/main.go @@ -16,19 +16,21 @@ package main import ( _ "embed" + "flag" + "os" "github.com/spf13/cobra/doc" "kfutil/cmd" ) func main() { - //var docsFlag bool - //flag.BoolVar(&docsFlag, "makedocs", false, "Create markdown docs.") - //flag.Parse() - //if docsFlag { - // docs() - // os.Exit(0) - //} + var docsFlag bool + flag.BoolVar(&docsFlag, "makedocs", false, "Create markdown docs.") + flag.Parse() + if docsFlag { + docs() + os.Exit(0) + } cmd.Execute() } From 210719a742cadbc79d201d76ec68eed19bdb60e0 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Tue, 17 Jun 2025 10:58:11 -0700 Subject: [PATCH 23/24] chore(docs): Update `stores import csv` docs to use product doc verbiage for schedule params. Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- cmd/storesBulkOperations.go | 14 ++++++++++---- docs/kfutil_stores_import_csv.md | 22 +++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/cmd/storesBulkOperations.go b/cmd/storesBulkOperations.go index a4c101f..4bbd4a4 100644 --- a/cmd/storesBulkOperations.go +++ b/cmd/storesBulkOperations.go @@ -132,13 +132,19 @@ Required Flags: | Password | This is equivalent to the 'StorePassword' field in the Command Certificate Store UI. | ###### Inventory Schedule Fields +For full information on certificate store schedules visit: https://software.keyfactor.com/Core-OnPrem/v25.1.1/Content/WebAPI/KeyfactorAPI/CertificateStoresPostSchedule.htm#API-Table-Schedule + +> [!NOTE] +> Only one type of schedule can be specified in the CSV file. If multiple are specified, +> the last one will be used. For example you can't schedule both "InventorySchedule.Immediate" and "InventorySchedule. +> Interval.Minutes", in which case the value of "InventorySchedule.Interval.Minutes" would be used. | Header | Description | | --- | --- | -| InventorySchedule.Immediate | Boolean value, set to "TRUE" to schedule immediate inventory | -| InventorySchedule.Interval.Minutes | The timeframe in which to periodically inventory int number/integer value. Ex.120 for 2 hours. | -| InventorySchedule.Daily.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | -| InventorySchedule.Weekly.Days | TBD | +| InventorySchedule.Immediate | A Boolean that indicates a job scheduled to run immediately (TRUE) or not (FALSE). | +| InventorySchedule.Interval.Minutes | An integer indicating the number of minutes between each interval. | +| InventorySchedule.Daily.Time | The date and time to next run the job. The date and time should be given using the ISO 8601 UTC time format "YYYY-MM-DDTHH:mm:ss.000Z"" (e.g. 2023-11-19T16:23:01Z). | +| InventorySchedule.Weekly.Days | An array of values representing the days of the week on which to run the job. These can either be entered as integers (0 for Sunday, 1 for Monday, etc.) or as days of the week (e.g. "Sunday"). | | InventorySchedule.Weekly.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | ##### Outside CSV file: diff --git a/docs/kfutil_stores_import_csv.md b/docs/kfutil_stores_import_csv.md index 3bfd01c..c34731e 100644 --- a/docs/kfutil_stores_import_csv.md +++ b/docs/kfutil_stores_import_csv.md @@ -25,13 +25,21 @@ Required Flags: ###### Inventory Schedule Fields -| Header | Description | -|------------------------------------|------------------------------------------------------------------------------------------------| -| InventorySchedule.Immediate | Boolean value, set to "TRUE" to schedule immediate inventory | -| InventorySchedule.Interval.Minutes | The timeframe in which to periodically inventory int number/integer value. Ex.120 for 2 hours. | -| InventorySchedule.Daily.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | -| InventorySchedule.Weekly.Days | TBD | -| InventorySchedule.Weekly.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | +For full information on certificate store schedules +visit: https://software.keyfactor.com/Core-OnPrem/v25.1.1/Content/WebAPI/KeyfactorAPI/CertificateStoresPostSchedule.htm#API-Table-Schedule + +> [!NOTE] +> Only one type of schedule can be specified in the CSV file. If multiple are specified, +> the last one will be used. For example you can't schedule both "InventorySchedule.Immediate" and "InventorySchedule. +> Interval.Minutes", in which case the value of "InventorySchedule.Interval.Minutes" would be used. + +| Header | Description | +|------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| InventorySchedule.Immediate | A Boolean that indicates a job scheduled to run immediately (TRUE) or not (FALSE). | +| InventorySchedule.Interval.Minutes | An integer indicating the number of minutes between each interval. | +| InventorySchedule.Daily.Time | The date and time to next run the job. The date and time should be given using the ISO 8601 UTC time format "YYYY-MM-DDTHH:mm:ss.000Z"" (e.g. 2023-11-19T16:23:01Z). | +| InventorySchedule.Weekly.Days | An array of values representing the days of the week on which to run the job. These can either be entered as integers (0 for Sunday, 1 for Monday, etc.) or as days of the week (e.g. "Sunday"). | +| InventorySchedule.Weekly.Time | The time of day to inventory daily, RFC3339 format. Ex. "2023-10-01T12:00:00Z" for noon UTC. | ##### Outside CSV file: If you do not wish to include credentials in your CSV file they can be provided one of three ways: From 6d30681ca072698fe69cf7ea0616dde30b95d850 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:08:27 -0700 Subject: [PATCH 24/24] chore(docs): Fix root-of-trust template commands on top level README.md Signed-off-by: spbsoluble <1661003+spbsoluble@users.noreply.github.com> --- README.md | 8 ++++---- readme_source.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f7f7d47..28efd8d 100644 --- a/README.md +++ b/README.md @@ -298,10 +298,10 @@ set of defined certificates are present in each store that meets a certain set o ```bash echo "Generating cert template file certs_template.csv" -kfutil stores rot generate-template-rot --type certs +kfutil stores rot generate-template --type certs # edit the certs_template.csv file echo "Generating stores template file stores_template.csv" -kfutil stores rot generate-template-rot --type stores +kfutil stores rot generate-template --type stores # edit the stores_template.csv file kfutil stores rot audit --add-certs certs_template.csv --stores stores_template.csv #This will audit the stores and generate a report file # review/edit the report file generated `rot_audit.csv` @@ -317,7 +317,7 @@ For full documentation, see [stores rot generate template](docs/kfutil_stores_ro This will write the file `certs_template.csv` to the current directory. ```bash -kfutil stores generate-template-rot --type certs +kfutil stores rot generate-template --type certs ``` #### Generate Certificate Store List Template @@ -327,7 +327,7 @@ For full documentation, see [stores rot generate template](docs/kfutil_stores_ro This will write the file `stores_template.csv` to the current directory. For full documentation ```bash -kfutil stores generate-template-rot --type stores +kfutil stores rot generate-template --type stores ``` #### Run Root of Trust Audit diff --git a/readme_source.md b/readme_source.md index 50a45c0..1b81598 100644 --- a/readme_source.md +++ b/readme_source.md @@ -276,10 +276,10 @@ set of defined certificates are present in each store that meets a certain set o ```bash echo "Generating cert template file certs_template.csv" -kfutil stores rot generate-template-rot --type certs +kfutil stores rot generate-template --type certs # edit the certs_template.csv file echo "Generating stores template file stores_template.csv" -kfutil stores rot generate-template-rot --type stores +kfutil stores rot generate-template --type stores # edit the stores_template.csv file kfutil stores rot audit --add-certs certs_template.csv --stores stores_template.csv #This will audit the stores and generate a report file # review/edit the report file generated `rot_audit.csv` @@ -295,7 +295,7 @@ For full documentation, see [stores rot generate template](docs/kfutil_stores_ro This will write the file `certs_template.csv` to the current directory. ```bash -kfutil stores generate-template-rot --type certs +kfutil stores rot generate-template --type certs ``` #### Generate Certificate Store List Template @@ -305,7 +305,7 @@ For full documentation, see [stores rot generate template](docs/kfutil_stores_ro This will write the file `stores_template.csv` to the current directory. For full documentation ```bash -kfutil stores generate-template-rot --type stores +kfutil stores rot generate-template --type stores ``` #### Run Root of Trust Audit