Skip to content
Open
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
2 changes: 2 additions & 0 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Config struct {
TLSKeyFile string
MutualTLSCAFile string
MutualTLSCNRegex string
MutualTLSSANRegex string
TLSRemoteCAs string
MutualTLSCertFile string
MutualTLSKeyFile string
Expand Down Expand Up @@ -83,6 +84,7 @@ func registerFlags(c *Config, f *flag.FlagSet) {
f.StringVar(&c.TLSKeyFile, "tls-key", "", "Other endpoint CA private key")
f.StringVar(&c.MutualTLSCAFile, "mutual-tls-ca", "", "Mutual TLS - require clients be signed by this CA ")
f.StringVar(&c.MutualTLSCNRegex, "mutual-tls-cn", "", "Mutual TLS - regex for whitelist of allowed client CNs")
f.StringVar(&c.MutualTLSSANRegex, "mutual-tls-san", "", "Mutual TLS - regex for whitelist of allowed client SANs")
f.StringVar(&c.TLSRemoteCAs, "tls-remote-ca", "", "CAs to trust for remote TLS requests")
f.StringVar(&c.MutualTLSCertFile, "mutual-tls-client-cert", "", "Mutual TLS - client certificate to call remote instance requiring client certs")
f.StringVar(&c.MutualTLSKeyFile, "mutual-tls-client-key", "", "Mutual TLS - client key to call remote instance requiring client certs")
Expand Down
31 changes: 28 additions & 3 deletions cli/serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ Usage of serve:
[-metadata file] [-remote remote_host] [-config config] \
[-responder cert] [-responder-key key] \
[-tls-cert cert] [-tls-key key] [-mutual-tls-ca ca] [-mutual-tls-cn regex] \
[-tls-remote-ca ca] [-mutual-tls-client-cert cert] [-mutual-tls-client-key key] \
[-db-config db-config] [-disable endpoint[,endpoint]]
[-mutual-tls-san regex] [-tls-remote-ca ca] [-mutual-tls-client-cert cert] \
[-mutual-tls-client-key key] [-db-config db-config] [-disable endpoint[,endpoint]]

Flags:
`

// Flags used by 'cfssl serve'
var serverFlags = []string{"address", "port", "min-tls-version", "ca", "ca-key", "ca-bundle", "int-bundle", "int-dir",
"metadata", "remote", "config", "responder", "responder-key", "tls-key", "tls-cert", "mutual-tls-ca",
"mutual-tls-cn", "tls-remote-ca", "mutual-tls-client-cert", "mutual-tls-client-key", "db-config", "disable"}
"mutual-tls-cn", "mutual-tls-san", "tls-remote-ca", "mutual-tls-client-cert", "mutual-tls-client-key", "db-config", "disable"}

var (
conf cli.Config
Expand Down Expand Up @@ -354,6 +354,31 @@ func serverMain(args []string, c cli.Config) error {
http.Error(w, "Invalid CN", http.StatusForbidden)
})
}

if conf.MutualTLSSANRegex != "" {
log.Debugf(`Requiring any SAN matches regex "%s" for client connections`, conf.MutualTLSSANRegex)
re, err := regexp.Compile(conf.MutualTLSSANRegex)
if err != nil {
return fmt.Errorf("malformed SAN regex: %s", err)
}
server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r != nil && r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
for _, name := range r.TLS.PeerCertificates[0].DNSNames {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SAN list includes more than DNS names; if you look at the Certificate structure, it has

        // Subject Alternate Name values
        DNSNames       []string
        EmailAddresses []string
        IPAddresses    []net.IP
        URIs           []*url.URL

so this should probably also check more than the DNS names.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Kisom,

I'd considered this, but, should it?

I wasn't too sure what the use-case would be for validating based on those other attributes, but, validating based on the DNSNames is ultimately arbitrary.

If I updated to validate against all of them, do you consider this merge ready/worthy?

-Adam

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamjacobmuller Other than that, it looks fine.

if re.MatchString(name) {
http.DefaultServeMux.ServeHTTP(w, r)
return
}
}
log.Warningf(`Rejected client cert CN "%s", SANs [%s] does not match regex %s`,
r.TLS.PeerCertificates[0].Subject.CommonName,
strings.Join(r.TLS.PeerCertificates[0].DNSNames, ", "),
conf.MutualTLSCNRegex,
)
}
http.Error(w, "No Valid SAN", http.StatusForbidden)
})
}

log.Info("Now listening with mutual TLS on https://", addr)
return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile)
}
Expand Down