mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 02:03:20 -04:00 
			
		
		
		
	Common tls (#474)
* Add common TLS config routines These routines can be used to load TLS configs based upon the args in the Corefile. * Add common routine for Corefile arg handling Add the NewTLSConfigFromArgs routine so that you can just pass in the Corefile args and get a tls.Config. This ensures the parameters are handled consistently across middleware. * Change to varargs style params Change to use args ...string instead of []string. Add documentation of what each call means.
This commit is contained in:
		
							
								
								
									
										104
									
								
								middleware/tls/tls.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								middleware/tls/tls.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| ) | ||||
|  | ||||
| // NewTLSConfigFromArgs returns a TLS config based upon the passed | ||||
| // in list of arguments. Typically these come straight from the | ||||
| // Corefile. | ||||
| // no args | ||||
| //  - creates a Config with no cert and using system CAs | ||||
| //  - use for a client that talks to a server with a public signed cert (CA installed in system) | ||||
| //  - the client will not be authenticated by the server since there is no cert | ||||
| // one arg: the path to CA PEM file | ||||
| //  - creates a Config with no cert using a specific CA | ||||
| //  - use for a client that talks to a server with a private signed cert (CA not installed in system) | ||||
| //  - the client will not be authenticated by the server since there is no cert | ||||
| // two args: path to cert PEM file, the path to private key PEM file | ||||
| //  - creates a Config with a cert, using system CAs to validate the other end | ||||
| //  - use for: | ||||
| //    - a server; or, | ||||
| //    - a client that talks to a server with a public cert and needs certificate-based authentication | ||||
| //  - the other end will authenticate this end via the provided cert | ||||
| //  - the cert of the other end will be verified via system CAs | ||||
| // three args: path to cert PEM file, path to client private key PEM file, path to CA PEM file | ||||
| //  - creates a Config with the cert, using specified CA to validate the other end | ||||
| //  - use for: | ||||
| //    - a server; or, | ||||
| //    - a client that talks to a server with a privately signed cert and needs certificate-based | ||||
| //      authentication | ||||
| //  - the other end will authenticate this end via the provided cert | ||||
| //  - this end will verify the other end's cert using the specified CA | ||||
| func NewTLSConfigFromArgs(args ...string) (*tls.Config, error) { | ||||
| 	var err error | ||||
| 	var c *tls.Config | ||||
| 	switch len(args) { | ||||
| 	case 0: | ||||
| 		// No client cert, use system CA | ||||
| 		c, err = NewTLSClientConfig("") | ||||
| 	case 1: | ||||
| 		// No client cert, use specified CA | ||||
| 		c, err = NewTLSClientConfig(args[0]) | ||||
| 	case 2: | ||||
| 		// Client cert, use system CA | ||||
| 		c, err = NewTLSConfig(args[0], args[1], "") | ||||
| 	case 3: | ||||
| 		// Client cert, use specified CA | ||||
| 		c, err = NewTLSConfig(args[0], args[1], args[2]) | ||||
| 	default: | ||||
| 		err = fmt.Errorf("Maximum of three arguments allowed for TLS config, found %d", len(args)) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return c, nil | ||||
| } | ||||
|  | ||||
| // NewTLSConfig returns a TLS config that includes a certificate | ||||
| // Use for server TLS config or when using a client certificate | ||||
| // If caPath is empty, system CAs will be used | ||||
| func NewTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) { | ||||
| 	cert, err := tls.LoadX509KeyPair(certPath, keyPath) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("Could not load TLS cert: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	roots, err := loadRoots(caPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &tls.Config{Certificates: []tls.Certificate{cert}, RootCAs: roots}, nil | ||||
| } | ||||
|  | ||||
| // NewTLSClientConfig returns a TLS config for a client connection | ||||
| // If caPath is empty, system CAs will be used | ||||
| func NewTLSClientConfig(caPath string) (*tls.Config, error) { | ||||
| 	roots, err := loadRoots(caPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &tls.Config{RootCAs: roots}, nil | ||||
| } | ||||
|  | ||||
| func loadRoots(caPath string) (*x509.CertPool, error) { | ||||
| 	if caPath == "" { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	roots := x509.NewCertPool() | ||||
| 	pem, err := ioutil.ReadFile(caPath) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("Error reading %s: %s", caPath, err) | ||||
| 	} | ||||
| 	ok := roots.AppendCertsFromPEM(pem) | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("Could not read root certs: %s", err) | ||||
| 	} | ||||
| 	return roots, nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user