Skip to content

Commit d369d8b

Browse files
committed
chore: Generated docs
chore(deps): Bump Keyfactor go client and cobra packages. feat: Added `--makedocs` to main to generate Markdown docs. fix(cmd): Exporting CLI root as `RootCmd` feat(cmd): Root of Trust (rot) audit file now includes cert and issuer DNs. fix(cmd): Root of Trust will now output an error if removing a cert fails. fix(cmd): Root of Trust will not output a message if an input store does not fit the root store criteria flags. fix(cmd): Shadowed variable caused `rot audit` to produce an empty file when only `--remove-certs` was passed. fix(cmd): Root of Trust will not output an error if it's unable to write a file to disk. fix(cmd): Root of Trust template generation will now output where template is written to. fix: storeTypes now use structs defined in the API client for: `PasswordOptions`, `EntryParameters`, and `SupportedOperations`
1 parent 917a51b commit d369d8b

37 files changed

+745
-50
lines changed

cmd/containers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ var containersListCmd = &cobra.Command{
9090
}
9191

9292
func init() {
93-
rootCmd.AddCommand(containersCmd)
93+
RootCmd.AddCommand(containersCmd)
9494
// LIST containers command
9595
containersCmd.AddCommand(containersListCmd)
9696
// GET containers command

cmd/orchs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ var listOrchestratorsCmd = &cobra.Command{
161161
func init() {
162162
var client string
163163

164-
rootCmd.AddCommand(orchsCmd)
164+
RootCmd.AddCommand(orchsCmd)
165165

166166
// LIST orchestrators command
167167
orchsCmd.AddCommand(listOrchestratorsCmd)

cmd/root.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
/*
22
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
3-
43
*/
54
package cmd
65

76
import (
8-
"os"
9-
107
"github.com/Keyfactor/keyfactor-go-client/api"
118
"github.com/spf13/cobra"
129
"log"
10+
"os"
1311
)
1412

1513
func initClient() (*api.Client, error) {
@@ -31,8 +29,8 @@ func initClient() (*api.Client, error) {
3129
return c, err
3230
}
3331

34-
// rootCmd represents the base command when called without any subcommands
35-
var rootCmd = &cobra.Command{
32+
// RootCmd represents the base command when called without any subcommands
33+
var RootCmd = &cobra.Command{
3634
Use: "kfutil",
3735
Short: "Keyfactor CLI utilities",
3836
Long: `A CLI wrapper around the Keyfactor Platform API.`,
@@ -44,7 +42,7 @@ var rootCmd = &cobra.Command{
4442
// Execute adds all child commands to the root command and sets flags appropriately.
4543
// This is called by main.main(). It only needs to happen once to the rootCmd.
4644
func Execute() {
47-
err := rootCmd.Execute()
45+
err := RootCmd.Execute()
4846
if err != nil {
4947
os.Exit(1)
5048
}
@@ -59,7 +57,7 @@ func init() {
5957

6058
// Cobra also supports local flags, which will only run
6159
// when this action is called directly.
62-
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
60+
RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
6361
}
6462

6563
func boolToPointer(b bool) *bool {

cmd/rot.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const (
5151
)
5252

5353
var (
54-
AuditHeader = []string{"Thumbprint", "CertID", "StoreID", "StoreType", "Machine", "Path", "AddCert", "RemoveCert", "Deployed"}
54+
AuditHeader = []string{"Thumbprint", "CertID", "SubjectName", "Issuer", "StoreID", "StoreType", "Machine", "Path", "AddCert", "RemoveCert", "Deployed"}
5555
StoreHeader = []string{"StoreID", "StoreType", "StoreMachine", "StorePath"}
5656
CertHeader = []string{"Thumbprint"}
5757
)
@@ -115,6 +115,7 @@ func generateAuditReport(addCerts map[string]string, removeCerts map[string]stri
115115
}
116116
certLookup, err := kfClient.GetCertificateContext(&certLookupReq)
117117
if err != nil {
118+
fmt.Printf("Error looking up certificate %s: %s\n", cert, err)
118119
log.Printf("[ERROR] Error looking up cert: %s\n%v", cert, err)
119120
continue
120121
}
@@ -123,20 +124,20 @@ func generateAuditReport(addCerts map[string]string, removeCerts map[string]stri
123124
for _, store := range stores {
124125
if _, ok := store.Thumbprints[cert]; ok {
125126
// Cert is already in the store do nothing
126-
row := []string{cert, certIDStr, store.ID, store.Type, store.Machine, store.Path, "false", "false", "true"}
127+
row := []string{cert, certIDStr, certLookup.IssuedDN, certLookup.IssuerDN, store.ID, store.Type, store.Machine, store.Path, "false", "false", "true"}
127128
data = append(data, row)
128129
wErr := csvWriter.Write(row)
129130
if wErr != nil {
130-
fmt.Printf("%s", wErr)
131+
fmt.Printf("Error writing audit file row: %s\n", wErr)
131132
log.Printf("[ERROR] Error writing audit row: %s", wErr)
132133
}
133134
} else {
134135
// Cert is not deployed to this store and will need to be added
135-
row := []string{cert, certIDStr, store.ID, store.Type, store.Machine, store.Path, "true", "false", "false"}
136+
row := []string{cert, certIDStr, certLookup.IssuedDN, certLookup.IssuerDN, store.ID, store.Type, store.Machine, store.Path, "true", "false", "false"}
136137
data = append(data, row)
137138
wErr := csvWriter.Write(row)
138139
if wErr != nil {
139-
fmt.Printf("%s", wErr)
140+
fmt.Printf("Error writing audit file row: %s\n", wErr)
140141
log.Printf("[ERROR] Error writing audit row: %s", wErr)
141142
}
142143
actions[cert] = append(actions[cert], ROTAction{
@@ -259,10 +260,11 @@ func reconcileRoots(actions map[string][]ROTAction, kfClient *api.Client, dryRun
259260
}
260261
_, err := kfClient.RemoveCertificateFromStores(&removeReq)
261262
if err != nil {
262-
fmt.Printf("Error removing cert %s (%d) from store %s (%s): %s", a.Thumbprint, a.CertID, a.StoreID, a.StorePath, err)
263-
log.Fatalf("[ERROR] Error removing cert from store: %s", err)
263+
fmt.Printf("Error removing cert %s (ID: %d) from store %s (%s): %s\n", a.Thumbprint, a.CertID, a.StoreID, a.StorePath, err)
264+
//log.Fatalf("[ERROR] Error removing cert from store: %s", err)
264265
}
265266
} else {
267+
fmt.Printf("DRY RUN: Would have removed cert %s from store %s\n", thumbprint, a.StoreID)
266268
log.Printf("[INFO] DRY RUN: Would have removed cert %s from store %s", thumbprint, a.StoreID)
267269
}
268270
}
@@ -325,7 +327,19 @@ var (
325327
rotCmd = &cobra.Command{
326328
Use: "rot",
327329
Short: "Root of trust utility",
328-
Long: `Root of trust allows you to manage your trusted roots using Keyfactor certificate stores.`,
330+
Long: `Root of trust allows you to manage your trusted roots using Keyfactor certificate stores.
331+
For example if you wish to add a list of "root" certs to a list of certificate stores you would simply generate and fill
332+
out the template CSV file. These template files can be generated with the following commands:
333+
kfutil stores rot generate-template --type certs
334+
kfutil stores rot generate-template --type stores
335+
Once those files are filled out you can use the following command to add the certs to the stores:
336+
kfutil stores rot audit --certs-file <certs-file> --stores-file <stores-file>
337+
Will generate a CSV report file 'rot_audit.csv' of what actions will be taken. If those actions are correct you can run
338+
the following command to actually perform the actions:
339+
kfutil stores rot reconcile --certs-file <certs-file> --stores-file <stores-file>
340+
OR if you want to used the audit report file generated you can run this command:
341+
kfutil stores rot reconcile --import-csv <audit-file>
342+
`,
329343
}
330344
rotAuditCmd = &cobra.Command{
331345
Use: "audit",
@@ -389,6 +403,7 @@ var (
389403
}
390404

391405
if !isRootStore(apiResp, inventory, minCerts, maxLeaves, maxKeys) {
406+
fmt.Printf("Store %s is not a root store, skipping.\n", entry[0])
392407
log.Printf("[WARN] Store %s is not a root store", apiResp.Id)
393408
continue
394409
} else {
@@ -437,11 +452,11 @@ var (
437452
// Read in the remove removeCerts CSV
438453
var certsToRemove = make(map[string]string)
439454
if removeRootsFile != "" {
440-
certsToRemove, rErr := readCertsFile(removeRootsFile, kfClient)
441-
if rErr != nil {
442-
fmt.Printf("Error reading removeCerts file: %s", rErr)
443-
log.Fatalf("Error reading removeCerts file: %s", rErr)
444-
}
455+
certsToRemove, _ = readCertsFile(removeRootsFile, kfClient)
456+
//if rErr != nil {
457+
// fmt.Printf("Error reading removeCerts file: %s", rErr)
458+
// log.Fatalf("Error reading removeCerts file: %s", rErr)
459+
//}
445460
removeCertsJSON, _ := json.Marshal(certsToRemove)
446461
log.Printf("[DEBUG] remove certs JSON: %s", string(removeCertsJSON))
447462
} else {
@@ -731,6 +746,7 @@ var (
731746
}
732747
file, err := os.Create(filePath)
733748
if err != nil {
749+
fmt.Printf("Error creating file: %s", err)
734750
log.Fatal("Cannot create file", err)
735751
}
736752

@@ -759,7 +775,7 @@ var (
759775
log.Fatal("Cannot write to file", err)
760776
}
761777
}
762-
778+
fmt.Printf("Template file created at %s", filePath)
763779
},
764780
RunE: nil,
765781
PostRun: nil,

cmd/status.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/*
22
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
3-
43
*/
54
package cmd
65

@@ -32,7 +31,7 @@ var statusCmd = &cobra.Command{
3231
}
3332

3433
func init() {
35-
rootCmd.AddCommand(statusCmd)
34+
RootCmd.AddCommand(statusCmd)
3635

3736
// Here you will define your flags and configuration settings.
3837

cmd/storeTypes.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -147,26 +147,16 @@ var storesTypeCreateCmd = &cobra.Command{
147147
Name: storeTypeConfig[storeType].(map[string]interface{})["Name"].(string),
148148
ShortName: storeTypeConfig[storeType].(map[string]interface{})["ShortName"].(string),
149149
Capability: storeTypeConfig[storeType].(map[string]interface{})["Capability"].(string),
150-
SupportedOperations: struct {
151-
Add bool `json:"Add"`
152-
Create bool `json:"Create"`
153-
Discovery bool `json:"Discovery"`
154-
Enrollment bool `json:"Enrollment"`
155-
Remove bool `json:"Remove"`
156-
}{
150+
SupportedOperations: &api.StoreTypeSupportedOperations{
157151
Add: storeTypeConfig[storeType].(map[string]interface{})["SupportedOperations"].(map[string]interface{})["Add"].(bool),
158152
Create: storeTypeConfig[storeType].(map[string]interface{})["SupportedOperations"].(map[string]interface{})["Create"].(bool),
159153
Discovery: storeTypeConfig[storeType].(map[string]interface{})["SupportedOperations"].(map[string]interface{})["Discovery"].(bool),
160154
Enrollment: storeTypeConfig[storeType].(map[string]interface{})["SupportedOperations"].(map[string]interface{})["Enrollment"].(bool),
161155
Remove: storeTypeConfig[storeType].(map[string]interface{})["SupportedOperations"].(map[string]interface{})["Remove"].(bool),
162156
},
163-
Properties: props,
164-
EntryParameters: []api.EntryParameter{},
165-
PasswordOptions: struct {
166-
EntrySupported bool `json:"EntrySupported"`
167-
StoreRequired bool `json:"StoreRequired"`
168-
Style string `json:"Style"`
169-
}{
157+
Properties: &props,
158+
EntryParameters: &[]api.EntryParameter{},
159+
PasswordOptions: &api.StoreTypePasswordOptions{
170160
EntrySupported: storeTypeConfig[storeType].(map[string]interface{})["PasswordOptions"].(map[string]interface{})["EntrySupported"].(bool),
171161
StoreRequired: storeTypeConfig[storeType].(map[string]interface{})["PasswordOptions"].(map[string]interface{})["StoreRequired"].(bool),
172162
Style: storeTypeConfig[storeType].(map[string]interface{})["PasswordOptions"].(map[string]interface{})["Style"].(string),
@@ -305,7 +295,7 @@ func getValidStoreTypes() []string {
305295
func init() {
306296

307297
validTypesString := strings.Join(getValidStoreTypes(), ", ")
308-
rootCmd.AddCommand(storeTypesCmd)
298+
RootCmd.AddCommand(storeTypesCmd)
309299

310300
// GET store type templates
311301
storeTypesCmd.AddCommand(fetchStoreTypes)

cmd/stores.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/*
22
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
3-
43
*/
54
package cmd
65

@@ -63,7 +62,7 @@ var storesGetCmd = &cobra.Command{
6362

6463
func init() {
6564
var storeId string
66-
rootCmd.AddCommand(storesCmd)
65+
RootCmd.AddCommand(storesCmd)
6766
storesCmd.AddCommand(storesListCmd)
6867
storesCmd.AddCommand(storesGetCmd)
6968
storesGetCmd.Flags().StringVarP(&storeId, "id", "i", "", "ID of the certificate store to get.")

docs/kfutil.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## kfutil
2+
3+
Keyfactor CLI utilities
4+
5+
### Synopsis
6+
7+
A CLI wrapper around the Keyfactor Platform API.
8+
9+
### Options
10+
11+
```
12+
-h, --help help for kfutil
13+
-t, --toggle Help message for toggle
14+
```
15+
16+
### SEE ALSO
17+
18+
* [kfutil containers](kfutil_containers.md) - Keyfactor CertificateStoreContainer API and utilities.
19+
* [kfutil orchs](kfutil_orchs.md) - Keyfactor agents/orchestrators APIs and utilities.
20+
* [kfutil status](kfutil_status.md) - List the status of Keyfactor services.
21+
* [kfutil store-types](kfutil_store-types.md) - Keyfactor certificate store types APIs and utilities.
22+
* [kfutil stores](kfutil_stores.md) - Keyfactor certificate stores APIs and utilities.
23+
24+
###### Auto generated by spf13/cobra on 24-Oct-2022

docs/kfutil_containers.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## kfutil containers
2+
3+
Keyfactor CertificateStoreContainer API and utilities.
4+
5+
### Synopsis
6+
7+
A collections of APIs and utilities for interacting with Keyfactor certificate store containers.
8+
9+
### Options
10+
11+
```
12+
-h, --help help for containers
13+
```
14+
15+
### SEE ALSO
16+
17+
* [kfutil](kfutil.md) - Keyfactor CLI utilities
18+
* [kfutil containers get](kfutil_containers_get.md) - Get certificate store container by ID or name.
19+
* [kfutil containers list](kfutil_containers_list.md) - List certificate store containers.
20+
21+
###### Auto generated by spf13/cobra on 24-Oct-2022

docs/kfutil_containers_get.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## kfutil containers get
2+
3+
Get certificate store container by ID or name.
4+
5+
### Synopsis
6+
7+
Get certificate store container by ID or name.
8+
9+
```
10+
kfutil containers get [flags]
11+
```
12+
13+
### Options
14+
15+
```
16+
-h, --help help for get
17+
-i, --id string ID or name of the cert store container.
18+
```
19+
20+
### SEE ALSO
21+
22+
* [kfutil containers](kfutil_containers.md) - Keyfactor CertificateStoreContainer API and utilities.
23+
24+
###### Auto generated by spf13/cobra on 24-Oct-2022

0 commit comments

Comments
 (0)