@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 01:00 UTC

master
go 122 lines 3.35 KB
Raw
1 // Copyright 2015 Matthew Holt and The Caddy Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package caddytls
16
17 import (
18 "crypto/tls"
19 "fmt"
20 "os"
21 "strings"
22
23 "github.com/caddyserver/caddy/v2"
24 )
25
26 func init() {
27 caddy.RegisterModule(FileLoader{})
28 }
29
30 // FileLoader loads certificates and their associated keys from disk.
31 type FileLoader []CertKeyFilePair
32
33 // Provision implements caddy.Provisioner.
34 func (fl FileLoader) Provision(ctx caddy.Context) error {
35 repl, ok := ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
36 if !ok {
37 repl = caddy.NewReplacer()
38 }
39 for k, pair := range fl {
40 for i, tag := range pair.Tags {
41 pair.Tags[i] = repl.ReplaceKnown(tag, "")
42 }
43 fl[k] = CertKeyFilePair{
44 Certificate: repl.ReplaceKnown(pair.Certificate, ""),
45 Key: repl.ReplaceKnown(pair.Key, ""),
46 Format: repl.ReplaceKnown(pair.Format, ""),
47 Tags: pair.Tags,
48 }
49 }
50 return nil
51 }
52
53 // CaddyModule returns the Caddy module information.
54 func (FileLoader) CaddyModule() caddy.ModuleInfo {
55 return caddy.ModuleInfo{
56 ID: "tls.certificates.load_files",
57 New: func() caddy.Module { return new(FileLoader) },
58 }
59 }
60
61 // CertKeyFilePair pairs certificate and key file names along with their
62 // encoding format so that they can be loaded from disk.
63 type CertKeyFilePair struct {
64 // Path to the certificate (public key) file.
65 Certificate string `json:"certificate"`
66
67 // Path to the private key file.
68 Key string `json:"key"`
69
70 // The format of the cert and key. Can be "pem". Default: "pem"
71 Format string `json:"format,omitempty"`
72
73 // Arbitrary values to associate with this certificate.
74 // Can be useful when you want to select a particular
75 // certificate when there may be multiple valid candidates.
76 Tags []string `json:"tags,omitempty"`
77 }
78
79 // LoadCertificates returns the certificates to be loaded by fl.
80 func (fl FileLoader) LoadCertificates() ([]Certificate, error) {
81 certs := make([]Certificate, 0, len(fl))
82 for _, pair := range fl {
83 certData, err := os.ReadFile(pair.Certificate)
84 if err != nil {
85 return nil, err
86 }
87 keyData, err := os.ReadFile(pair.Key)
88 if err != nil {
89 return nil, err
90 }
91
92 var cert tls.Certificate
93 switch pair.Format {
94 case "":
95 fallthrough
96
97 case "pem":
98 // if the start of the key file looks like an encrypted private key,
99 // reject it with a helpful error message
100 if strings.Contains(string(keyData[:40]), "ENCRYPTED") {
101 return nil, fmt.Errorf("encrypted private keys are not supported; please decrypt the key first")
102 }
103
104 cert, err = tls.X509KeyPair(certData, keyData)
105
106 default:
107 return nil, fmt.Errorf("unrecognized certificate/key encoding format: %s", pair.Format)
108 }
109 if err != nil {
110 return nil, err
111 }
112
113 certs = append(certs, Certificate{Certificate: cert, Tags: pair.Tags})
114 }
115 return certs, nil
116 }
117
118 // Interface guard
119 var (
120 _ CertificateLoader = FileLoader(nil)
121 _ caddy.Provisioner = FileLoader(nil)
122 )