Skip to content

cli: add --cert-principal-map to cert list command #48013

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 12 additions & 40 deletions pkg/base/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/util/envutil"
"github.com/cockroachdb/cockroach/pkg/util/mon"
"github.com/cockroachdb/cockroach/pkg/util/retry"
"github.com/cockroachdb/cockroach/pkg/util/stop"
)

// Base config defaults.
Expand Down Expand Up @@ -267,17 +266,17 @@ func (cfg *Config) AdminURL() *url.URL {
}
}

// GetClientCertPaths returns the paths to the client cert and key.
func (cfg *Config) GetClientCertPaths(user string) (string, string, error) {
// getClientCertPaths returns the paths to the client cert and key.
func (cfg *Config) getClientCertPaths(user string) (string, string, error) {
cm, err := cfg.GetCertificateManager()
if err != nil {
return "", "", err
}
return cm.GetClientCertPaths(user)
}

// GetCACertPath returns the path to the CA certificate.
func (cfg *Config) GetCACertPath() (string, error) {
// getCACertPath returns the path to the CA certificate.
func (cfg *Config) getCACertPath() (string, error) {
cm, err := cfg.GetCertificateManager()
if err != nil {
return "", err
Expand All @@ -304,7 +303,7 @@ func (cfg *Config) LoadSecurityOptions(options url.Values, username string) erro
// verify-ca and verify-full need a CA certificate.
if options.Get("sslrootcert") == "" {
// Fetch CA cert. This is required.
caCertPath, err := cfg.GetCACertPath()
caCertPath, err := cfg.getCACertPath()
if err != nil {
return wrapError(err)
}
Expand All @@ -316,7 +315,7 @@ func (cfg *Config) LoadSecurityOptions(options url.Values, username string) erro
}

// Fetch certs, but don't fail, we may be using a password.
certPath, keyPath, err := cfg.GetClientCertPaths(username)
certPath, keyPath, err := cfg.getClientCertPaths(username)
if err == nil {
if options.Get("sslcert") == "" {
options.Set("sslcert", certPath)
Expand Down Expand Up @@ -354,36 +353,6 @@ func (cfg *Config) GetCertificateManager() (*security.CertificateManager, error)
return cfg.certificateManager.cm, cfg.certificateManager.err
}

// InitializeNodeTLSConfigs tries to load client and server-side TLS configs.
// It also enables the reload-on-SIGHUP functionality on the certificate manager.
// This should be called early in the life of the server to make sure there are no
// issues with TLS configs.
// Returns the certificate manager if successfully created and in secure mode.
func (cfg *Config) InitializeNodeTLSConfigs(
stopper *stop.Stopper,
) (*security.CertificateManager, error) {
if cfg.Insecure {
return nil, nil
}

if _, err := cfg.GetServerTLSConfig(); err != nil {
return nil, err
}
if _, err := cfg.GetUIServerTLSConfig(); err != nil {
return nil, err
}
if _, err := cfg.GetClientTLSConfig(); err != nil {
return nil, err
}

cm, err := cfg.GetCertificateManager()
if err != nil {
return nil, err
}
cm.RegisterSignalHandler(stopper)
return cm, nil
}

// GetClientTLSConfig returns the client TLS config, initializing it if needed.
// If Insecure is true, return a nil config, otherwise ask the certificate
// manager for a TLS config using certs for the config.User.
Expand All @@ -406,11 +375,11 @@ func (cfg *Config) GetClientTLSConfig() (*tls.Config, error) {
return tlsCfg, nil
}

// GetUIClientTLSConfig returns the client TLS config for Admin UI clients, initializing it if needed.
// getUIClientTLSConfig returns the client TLS config for Admin UI clients, initializing it if needed.
// If Insecure is true, return a nil config, otherwise ask the certificate
// manager for a TLS config configured to talk to the Admin UI.
// This TLSConfig is **NOT** suitable to talk to the GRPC or SQL servers, use GetClientTLSConfig instead.
func (cfg *Config) GetUIClientTLSConfig() (*tls.Config, error) {
func (cfg *Config) getUIClientTLSConfig() (*tls.Config, error) {
// Early out.
if cfg.Insecure {
return nil, nil
Expand Down Expand Up @@ -452,6 +421,9 @@ func (cfg *Config) GetServerTLSConfig() (*tls.Config, error) {
// GetUIServerTLSConfig returns the server TLS config for the Admin UI, initializing it if needed.
// If Insecure is true, return a nil config, otherwise ask the certificate
// manager for a server UI TLS config.
//
// TODO(peter): This method is only used by `server.NewServer` and
// `Server.Start`. Move it.
func (cfg *Config) GetUIServerTLSConfig() (*tls.Config, error) {
// Early out.
if cfg.Insecure || cfg.DisableTLSForHTTP {
Expand All @@ -477,7 +449,7 @@ func (cfg *Config) GetHTTPClient() (http.Client, error) {
cfg.httpClient.httpClient.Timeout = 10 * time.Second
var transport http.Transport
cfg.httpClient.httpClient.Transport = &transport
transport.TLSClientConfig, cfg.httpClient.err = cfg.GetUIClientTLSConfig()
transport.TLSClientConfig, cfg.httpClient.err = cfg.getUIClientTLSConfig()
})

return cfg.httpClient.httpClient, cfg.httpClient.err
Expand Down
7 changes: 5 additions & 2 deletions pkg/cli/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,12 @@ List certificates and keys found in the certificate directory.

// runListCerts loads and lists all certs.
func runListCerts(cmd *cobra.Command, args []string) error {
cm, err := baseCfg.GetCertificateManager()
if err := security.SetCertPrincipalMap(certCtx.certPrincipalMap); err != nil {
return err
}
cm, err := security.NewCertificateManager(baseCfg.SSLCertsDir)
if err != nil {
return errors.Wrap(err, "could not get certificate manager")
return errors.Wrap(err, "cannot load certificates")
}

fmt.Fprintf(os.Stdout, "Certificate directory: %s\n", baseCfg.SSLCertsDir)
Expand Down
8 changes: 8 additions & 0 deletions pkg/cli/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ func initCLIDefaults() {

authCtx.validityPeriod = 1 * time.Hour

certCtx.certPrincipalMap = nil

initPreFlagsDefaults()

// Clear the "Changed" state of all the registered command-line flags.
Expand Down Expand Up @@ -393,3 +395,9 @@ var demoCtx struct {
transientCluster *transientCluster
insecure bool
}

// certCtx captures the command-line parameters of the `cert` command.
// Defaults set by InitCLIDefaults() above.
var certCtx struct {
certPrincipalMap []string
}
4 changes: 4 additions & 0 deletions pkg/cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ func init() {
StringFlag(f, &baseCfg.SSLCertsDir, cliflags.CertsDir, baseCfg.SSLCertsDir)
}

// The list certs command needs the certificate principal map.
StringSlice(listCertsCmd.Flags(), &certCtx.certPrincipalMap,
cliflags.CertPrincipalMap, certCtx.certPrincipalMap)

for _, cmd := range []*cobra.Command{createCACertCmd, createClientCACertCmd} {
f := cmd.Flags()
// CA certificates have a longer expiration time.
Expand Down
6 changes: 6 additions & 0 deletions pkg/cli/interactive_tests/test_cert_advisory_validation.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ interrupt
eexpect "interrupted"
expect $prompt
end_test

start_test "Check that 'cert list' can utilize cert principal map."
send "$argv cert list --certs-dir=$certs_dir --cert-principal-map=foo.bar:node\r"
eexpect "Certificate directory:"
expect $prompt
end_test
23 changes: 18 additions & 5 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,24 @@ func NewServer(cfg Config, stopper *stop.Stopper) (*Server, error) {
}

// Attempt to load TLS configs right away, failures are permanent.
if certMgr, err := cfg.InitializeNodeTLSConfigs(stopper); err != nil {
return nil, err
} else if certMgr != nil {
// The certificate manager is non-nil in secure mode.
registry.AddMetricStruct(certMgr.Metrics())
if !cfg.Insecure {
// TODO(peter): Call methods on CertificateManager directly. Need to call
// base.wrapError or similar on the resulting error.
if _, err := cfg.GetServerTLSConfig(); err != nil {
return nil, err
}
if _, err := cfg.GetUIServerTLSConfig(); err != nil {
return nil, err
}
if _, err := cfg.GetClientTLSConfig(); err != nil {
return nil, err
}
cm, err := cfg.GetCertificateManager()
if err != nil {
return nil, err
}
cm.RegisterSignalHandler(stopper)
registry.AddMetricStruct(cm.Metrics())
}

// Add a dynamic log tag value for the node ID.
Expand Down