Skip to content

Commit 0f7ef88

Browse files
authored
Merge pull request #2782 from diazjf/fix-2756
Add Better Error Handling for SSLSessionTicketKey
2 parents 32fe402 + 52ecdf0 commit 0f7ef88

File tree

4 files changed

+72
-13
lines changed

4 files changed

+72
-13
lines changed

docs/user-guide/nginx-configuration/configmap.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,9 @@ Enables or disables session resumption through [TLS session tickets](http://ngin
434434
## ssl-session-ticket-key
435435

436436
Sets the secret key used to encrypt and decrypt TLS session tickets. The value must be a valid base64 string.
437+
To create a ticket: `openssl rand 80 | openssl enc -A -base64`
437438

438-
[TLS session ticket-key](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets), by default, a randomly generated key is used. To create a ticket: `openssl rand 80 | base64 -w0`
439+
[TLS session ticket-key](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets), by default, a randomly generated key is used.
439440

440441
## ssl-session-timeout
441442

internal/ingress/controller/config/config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ type Configuration struct {
303303
// Sets the secret key used to encrypt and decrypt TLS session tickets.
304304
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets
305305
// By default, a randomly generated key is used.
306-
// Example: openssl rand 80 | base64 -w0
306+
// Example: openssl rand 80 | openssl enc -A -base64
307307
SSLSessionTicketKey string `json:"ssl-session-ticket-key,omitempty"`
308308

309309
// Time during which a client may reuse the session parameters stored in a cache.

internal/ingress/controller/store/store.go

+30-11
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@ func New(checkOCSP bool,
521521
if err != nil {
522522
glog.Warningf("Unexpected error reading configuration configmap: %v", err)
523523
}
524-
store.setConfig(cm)
525524

525+
store.setConfig(cm)
526526
return store
527527
}
528528

@@ -708,6 +708,34 @@ func (s k8sStore) GetAuthCertificate(name string) (*resolver.AuthSSLCert, error)
708708
}, nil
709709
}
710710

711+
func (s k8sStore) writeSSLSessionTicketKey(cmap *corev1.ConfigMap, fileName string) {
712+
ticketString := ngx_template.ReadConfig(cmap.Data).SSLSessionTicketKey
713+
s.backendConfig.SSLSessionTicketKey = ""
714+
715+
if ticketString != "" {
716+
ticketBytes := base64.StdEncoding.WithPadding(base64.StdPadding).DecodedLen(len(ticketString))
717+
718+
// 81 used instead of 80 because of padding
719+
if !(ticketBytes == 48 || ticketBytes == 81) {
720+
glog.Warningf("ssl-session-ticket-key must contain either 48 or 80 bytes")
721+
}
722+
723+
decodedTicket, err := base64.StdEncoding.DecodeString(ticketString)
724+
if err != nil {
725+
glog.Errorf("unexpected error decoding ssl-session-ticket-key: %v", err)
726+
return
727+
}
728+
729+
err = ioutil.WriteFile(fileName, decodedTicket, file.ReadWriteByUser)
730+
if err != nil {
731+
glog.Errorf("unexpected error writing ssl-session-ticket-key to %s: %v", fileName, err)
732+
return
733+
}
734+
735+
s.backendConfig.SSLSessionTicketKey = ticketString
736+
}
737+
}
738+
711739
// GetDefaultBackend returns the default backend
712740
func (s k8sStore) GetDefaultBackend() defaults.Backend {
713741
return s.backendConfig.Backend
@@ -719,16 +747,7 @@ func (s k8sStore) GetBackendConfiguration() ngx_config.Configuration {
719747

720748
func (s *k8sStore) setConfig(cmap *corev1.ConfigMap) {
721749
s.backendConfig = ngx_template.ReadConfig(cmap.Data)
722-
723-
// TODO: this should not be done here
724-
if s.backendConfig.SSLSessionTicketKey != "" {
725-
d, err := base64.StdEncoding.DecodeString(s.backendConfig.SSLSessionTicketKey)
726-
if err != nil {
727-
glog.Warningf("unexpected error decoding key ssl-session-ticket-key: %v", err)
728-
s.backendConfig.SSLSessionTicketKey = ""
729-
}
730-
ioutil.WriteFile("/etc/nginx/tickets.key", d, file.ReadWriteByUser)
731-
}
750+
s.writeSSLSessionTicketKey(cmap, "/etc/nginx/tickets.key")
732751
}
733752

734753
// Run initiates the synchronization of the informers and the initial

internal/ingress/controller/store/store_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ import (
3333
"k8s.io/client-go/kubernetes"
3434
"k8s.io/client-go/tools/cache"
3535

36+
"encoding/base64"
37+
"io/ioutil"
38+
"k8s.io/api/core/v1"
3639
"k8s.io/ingress-nginx/internal/file"
3740
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
3841
"k8s.io/ingress-nginx/test/e2e/framework"
@@ -828,3 +831,39 @@ func TestListIngresses(t *testing.T) {
828831
t.Errorf("Expected 3 Ingresses but got %v", s)
829832
}
830833
}
834+
835+
func TestWriteSSLSessionTicketKey(t *testing.T) {
836+
tests := []string{
837+
"9DyULjtYWz520d1rnTLbc4BOmN2nLAVfd3MES/P3IxWuwXkz9Fby0lnOZZUdNEMV",
838+
"9SvN1C9AB5DvNde5fMKoJwAwICpqdjiMyxR+cv6NpAWv22rFd3gKt4wMyGxCm7l9Wh6BQPG0+csyBZSHHr2NOWj52Wx8xCegXf4NsSMBUqA=",
839+
}
840+
841+
for _, test := range tests {
842+
s := newStore(t)
843+
844+
cmap := &v1.ConfigMap{
845+
Data: map[string]string{
846+
"ssl-session-ticket-key": test,
847+
},
848+
}
849+
850+
f, err := ioutil.TempFile("", "ssl-session-ticket-test")
851+
if err != nil {
852+
t.Fatal(err)
853+
}
854+
855+
s.writeSSLSessionTicketKey(cmap, f.Name())
856+
857+
content, err := ioutil.ReadFile(f.Name())
858+
if err != nil {
859+
t.Fatal(err)
860+
}
861+
encodedContent := base64.StdEncoding.EncodeToString(content)
862+
863+
f.Close()
864+
865+
if test != encodedContent {
866+
t.Fatalf("expected %v but returned %s", test, encodedContent)
867+
}
868+
}
869+
}

0 commit comments

Comments
 (0)