Skip to content

Commit

Permalink
feat: Support multiple active CAs in tctl auth export (#51298) (#51376
Browse files Browse the repository at this point in the history
)

* Support multiple active CAs in `tctl auth export`

* Remove the ExportAuthoritiesSecrets func

* Mention path in the --out-prefix help

* Rename --out-prefix to --out

* Write script-friendly output
  • Loading branch information
codingllama authored Jan 22, 2025
1 parent a615596 commit f2c9ea4
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 15 deletions.
9 changes: 0 additions & 9 deletions lib/client/ca_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,6 @@ func ExportAuthorities(ctx context.Context, client authclient.ClientI, req Expor
return exportAuthorities(ctx, client, req, ExportAllAuthorities)
}

// ExportAuthoritiesSecrets is the single-authority variant of
// [ExportAllAuthoritiesSecrets].
// Soft-deprecated, prefer using [ExportAllAuthoritiesSecrets] and handling
// exports with more than one authority gracefully.
func ExportAuthoritiesSecrets(ctx context.Context, client authclient.ClientI, req ExportAuthoritiesRequest) (string, error) {
// TODO(codingllama): Remove ExportAuthoritiesSecrets.
return exportAuthorities(ctx, client, req, ExportAllAuthoritiesSecrets)
}

func exportAuthorities(
ctx context.Context,
client authclient.ClientI,
Expand Down
3 changes: 0 additions & 3 deletions lib/client/ca_export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,6 @@ func TestExportAuthorities(t *testing.T) {
t.Run(fmt.Sprintf("%s/ExportAllAuthoritiesSecrets", tt.name), func(t *testing.T) {
runTest(t, ExportAllAuthoritiesSecrets, tt.assertSecrets)
})
t.Run(fmt.Sprintf("%s/ExportAuthoritiesSecrets", tt.name), func(t *testing.T) {
runUnaryTest(t, ExportAuthoritiesSecrets, tt.assertSecrets)
})
})
}
}
Expand Down
30 changes: 27 additions & 3 deletions tool/tctl/common/auth_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ func (a *AuthCommand) Initialize(app *kingpin.Application, config *servicecfg.Co
a.authExport.Flag("type",
fmt.Sprintf("export certificate type (%v)", strings.Join(allowedCertificateTypes, ", "))).
EnumVar(&a.authType, allowedCertificateTypes...)
a.authExport.
Flag("out", "If set writes exported authorities to files with the given path prefix").
StringVar(&a.output)

a.authGenerate = auth.Command("gen", "Generate a new SSH keypair.").Hidden()
a.authGenerate.Flag("pub-key", "path to the public key").Required().StringVar(&a.genPubPath)
Expand Down Expand Up @@ -220,9 +223,9 @@ var allowedCRLCertificateTypes = []string{
// If --type flag is given, only prints keys for CAs of this type, otherwise
// prints all keys
func (a *AuthCommand) ExportAuthorities(ctx context.Context, clt *authclient.Client) error {
exportFunc := client.ExportAuthorities
exportFunc := client.ExportAllAuthorities
if a.exportPrivateKeys {
exportFunc = client.ExportAuthoritiesSecrets
exportFunc = client.ExportAllAuthoritiesSecrets
}

authorities, err := exportFunc(
Expand All @@ -238,8 +241,29 @@ func (a *AuthCommand) ExportAuthorities(ctx context.Context, clt *authclient.Cli
return trace.Wrap(err)
}

fmt.Println(authorities)
if l := len(authorities); l > 1 && a.output == "" {
return trace.BadParameter("found %d authorities to export, use --out to export all", l)
}

if a.output != "" {
perms := os.FileMode(0644)
if a.exportPrivateKeys {
perms = 0600
}

fmt.Fprintf(os.Stderr, "Writing %d files with prefix %q\n", len(authorities), a.output)
for i, authority := range authorities {
name := fmt.Sprintf("%s%d.cer", a.output, i)
if err := os.WriteFile(name, authority.Data, perms); err != nil {
return trace.Wrap(err)
}
fmt.Println(name)
}
return nil
}

// Only a single CA is exported if we got this far.
fmt.Printf("%s\n", authorities[0].Data)
return nil
}

Expand Down

0 comments on commit f2c9ea4

Please sign in to comment.