Merge pull request #4273 from aledbf/ssh-chain-dynamic
Check and complete intermediate SSL certificates
This commit is contained in:
commit
930e37a0b5
13 changed files with 132 additions and 214 deletions
|
@ -131,8 +131,7 @@ Requires the update-status parameter.`)
|
|||
|
||||
enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", false,
|
||||
`Autocomplete SSL certificate chains with missing intermediate CA certificates.
|
||||
A valid certificate chain is required to enable OCSP stapling. Certificates
|
||||
uploaded to Kubernetes must have the "Authority Information Access" X.509 v3
|
||||
Certificates uploaded to Kubernetes must have the "Authority Information Access" X.509 v3
|
||||
extension for this to succeed.`)
|
||||
|
||||
syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
|
||||
|
@ -142,9 +141,8 @@ extension for this to succeed.`)
|
|||
`Customized address to set as the load-balancer status of Ingress objects this controller satisfies.
|
||||
Requires the update-status parameter.`)
|
||||
|
||||
dynamicCertificatesEnabled = flags.Bool("enable-dynamic-certificates", true,
|
||||
`Dynamically update SSL certificates instead of reloading NGINX.
|
||||
Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not enabled`)
|
||||
enableDynamicCertificates = flags.Bool("enable-dynamic-certificates", true,
|
||||
`Dynamically update SSL certificates instead of reloading NGINX. Feature backed by OpenResty Lua libraries.`)
|
||||
|
||||
enableMetrics = flags.Bool("enable-metrics", true,
|
||||
`Enables the collection of NGINX metrics`)
|
||||
|
@ -223,10 +221,6 @@ Takes the form "<host>:port". If not provided, no admission controller is starte
|
|||
klog.Warningf("SSL certificate chain completion is disabled (--enable-ssl-chain-completion=false)")
|
||||
}
|
||||
|
||||
if *enableSSLChainCompletion && *dynamicCertificatesEnabled {
|
||||
return false, nil, fmt.Errorf(`SSL certificate chain completion cannot be enabled when dynamic certificates functionality is enabled. Please check the flags --enable-ssl-chain-completion`)
|
||||
}
|
||||
|
||||
if *publishSvc != "" && *publishStatusAddress != "" {
|
||||
return false, nil, fmt.Errorf("Flags --publish-service and --publish-status-address are mutually exclusive")
|
||||
}
|
||||
|
@ -237,6 +231,9 @@ Takes the form "<host>:port". If not provided, no admission controller is starte
|
|||
nginx.HealthCheckTimeout = time.Duration(*defHealthCheckTimeout) * time.Second
|
||||
}
|
||||
|
||||
ngx_config.EnableSSLChainCompletion = *enableSSLChainCompletion
|
||||
ngx_config.EnableDynamicCertificates = *enableDynamicCertificates
|
||||
|
||||
config := &controller.Configuration{
|
||||
APIServerHost: *apiserverHost,
|
||||
KubeConfigFile: *kubeConfigFile,
|
||||
|
@ -246,7 +243,6 @@ Takes the form "<host>:port". If not provided, no admission controller is starte
|
|||
EnableMetrics: *enableMetrics,
|
||||
MetricsPerHost: *metricsPerHost,
|
||||
EnableSSLPassthrough: *enableSSLPassthrough,
|
||||
EnableSSLChainCompletion: *enableSSLChainCompletion,
|
||||
ResyncPeriod: *resyncPeriod,
|
||||
DefaultService: *defaultSvc,
|
||||
Namespace: *watchNamespace,
|
||||
|
@ -259,7 +255,6 @@ Takes the form "<host>:port". If not provided, no admission controller is starte
|
|||
UpdateStatusOnShutdown: *updateStatusOnShutdown,
|
||||
UseNodeInternalIP: *useNodeInternalIP,
|
||||
SyncRateLimit: *syncRateLimit,
|
||||
DynamicCertificatesEnabled: *dynamicCertificatesEnabled,
|
||||
ListenPorts: &ngx_config.ListenPorts{
|
||||
Default: *defServerPort,
|
||||
Health: *healthzPort,
|
||||
|
|
|
@ -30,6 +30,13 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
// EnableSSLChainCompletion Autocomplete SSL certificate chains with missing intermediate CA certificates.
|
||||
EnableSSLChainCompletion = false
|
||||
// EnableDynamicCertificates Dynamically update SSL certificates instead of reloading NGINX
|
||||
EnableDynamicCertificates = true
|
||||
)
|
||||
|
||||
const (
|
||||
// http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size
|
||||
// Sets the maximum allowed size of the client request body
|
||||
|
@ -772,7 +779,7 @@ type TemplateConfig struct {
|
|||
RedirectServers interface{}
|
||||
ListenPorts *ListenPorts
|
||||
PublishService *apiv1.Service
|
||||
DynamicCertificatesEnabled bool
|
||||
EnableDynamicCertificates bool
|
||||
EnableMetrics bool
|
||||
|
||||
PID string
|
||||
|
|
|
@ -84,14 +84,10 @@ type Configuration struct {
|
|||
EnableMetrics bool
|
||||
MetricsPerHost bool
|
||||
|
||||
EnableSSLChainCompletion bool
|
||||
|
||||
FakeCertificate *ingress.SSLCert
|
||||
|
||||
SyncRateLimit float32
|
||||
|
||||
DynamicCertificatesEnabled bool
|
||||
|
||||
DisableCatchAll bool
|
||||
|
||||
ValidationWebhook string
|
||||
|
@ -171,7 +167,7 @@ func (n *NGINXController) syncIngress(interface{}) error {
|
|||
}
|
||||
|
||||
err := wait.ExponentialBackoff(retry, func() (bool, error) {
|
||||
err := configureDynamically(pcfg, n.cfg.DynamicCertificatesEnabled)
|
||||
err := configureDynamically(pcfg)
|
||||
if err == nil {
|
||||
klog.V(2).Infof("Dynamic reconfiguration succeeded.")
|
||||
return true, nil
|
||||
|
@ -890,7 +886,7 @@ func (n *NGINXController) serviceEndpoints(svcKey, backendPort string) ([]ingres
|
|||
return upstreams, nil
|
||||
}
|
||||
|
||||
// overridePemFileNameAndPemSHA should only be called when DynamicCertificatesEnabled
|
||||
// overridePemFileNameAndPemSHA should only be called when EnableDynamicCertificates
|
||||
// ideally this function should not exist, the only reason why we use it is that
|
||||
// we rely on PemFileName in nginx.tmpl to configure SSL directives
|
||||
// and PemSHA to force reload
|
||||
|
@ -940,7 +936,7 @@ func (n *NGINXController) createServers(data []*ingress.Ingress,
|
|||
certificate, err := n.store.GetLocalSSLCert(n.cfg.DefaultSSLCertificate)
|
||||
if err == nil {
|
||||
defaultCertificate = certificate
|
||||
if n.cfg.DynamicCertificatesEnabled {
|
||||
if ngx_config.EnableDynamicCertificates {
|
||||
n.overridePemFileNameAndPemSHA(defaultCertificate)
|
||||
}
|
||||
} else {
|
||||
|
@ -1123,7 +1119,7 @@ func (n *NGINXController) createServers(data []*ingress.Ingress,
|
|||
}
|
||||
}
|
||||
|
||||
if n.cfg.DynamicCertificatesEnabled {
|
||||
if ngx_config.EnableDynamicCertificates {
|
||||
n.overridePemFileNameAndPemSHA(cert)
|
||||
}
|
||||
|
||||
|
|
|
@ -1116,7 +1116,7 @@ func newNGINXController(t *testing.T) *NGINXController {
|
|||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
storer := store.New(true,
|
||||
storer := store.New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -1126,7 +1126,6 @@ func newNGINXController(t *testing.T) *NGINXController {
|
|||
clientSet,
|
||||
fs,
|
||||
channels.NewRingChannel(10),
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
|
|
@ -129,7 +129,6 @@ func NewNGINXController(config *Configuration, mc metric.Collector, fs file.File
|
|||
n.podInfo = pod
|
||||
|
||||
n.store = store.New(
|
||||
config.EnableSSLChainCompletion,
|
||||
config.Namespace,
|
||||
config.ConfigMapName,
|
||||
config.TCPConfigMapName,
|
||||
|
@ -139,7 +138,6 @@ func NewNGINXController(config *Configuration, mc metric.Collector, fs file.File
|
|||
config.Client,
|
||||
fs,
|
||||
n.updateCh,
|
||||
config.DynamicCertificatesEnabled,
|
||||
pod,
|
||||
config.DisableCatchAll)
|
||||
|
||||
|
@ -614,7 +612,7 @@ func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressC
|
|||
IsSSLPassthroughEnabled: n.cfg.EnableSSLPassthrough,
|
||||
ListenPorts: n.cfg.ListenPorts,
|
||||
PublishService: n.GetPublishService(),
|
||||
DynamicCertificatesEnabled: n.cfg.DynamicCertificatesEnabled,
|
||||
EnableDynamicCertificates: ngx_config.EnableDynamicCertificates,
|
||||
EnableMetrics: n.cfg.EnableMetrics,
|
||||
|
||||
HealthzURI: nginx.HealthPath,
|
||||
|
@ -851,7 +849,7 @@ func (n *NGINXController) IsDynamicConfigurationEnough(pcfg *ingress.Configurati
|
|||
copyOfRunningConfig.ControllerPodsCount = 0
|
||||
copyOfPcfg.ControllerPodsCount = 0
|
||||
|
||||
if n.cfg.DynamicCertificatesEnabled {
|
||||
if ngx_config.EnableDynamicCertificates {
|
||||
clearCertificates(©OfRunningConfig)
|
||||
clearCertificates(©OfPcfg)
|
||||
}
|
||||
|
@ -861,7 +859,7 @@ func (n *NGINXController) IsDynamicConfigurationEnough(pcfg *ingress.Configurati
|
|||
|
||||
// configureDynamically encodes new Backends in JSON format and POSTs the
|
||||
// payload to an internal HTTP endpoint handled by Lua.
|
||||
func configureDynamically(pcfg *ingress.Configuration, isDynamicCertificatesEnabled bool) error {
|
||||
func configureDynamically(pcfg *ingress.Configuration) error {
|
||||
backends := make([]*ingress.Backend, len(pcfg.Backends))
|
||||
|
||||
for i, backend := range pcfg.Backends {
|
||||
|
@ -949,7 +947,7 @@ func configureDynamically(pcfg *ingress.Configuration, isDynamicCertificatesEnab
|
|||
return fmt.Errorf("unexpected error code: %d", statusCode)
|
||||
}
|
||||
|
||||
if isDynamicCertificatesEnabled {
|
||||
if ngx_config.EnableDynamicCertificates {
|
||||
err = configureCertificates(pcfg)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -32,10 +32,14 @@ import (
|
|||
apiv1 "k8s.io/api/core/v1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/nginx"
|
||||
)
|
||||
|
||||
func TestIsDynamicConfigurationEnough(t *testing.T) {
|
||||
ngx_config.EnableDynamicCertificates = false
|
||||
defer func() { ngx_config.EnableDynamicCertificates = true }()
|
||||
|
||||
backends := []*ingress.Backend{{
|
||||
Name: "fakenamespace-myapp-80",
|
||||
Endpoints: []ingress.Endpoint{
|
||||
|
@ -73,9 +77,7 @@ func TestIsDynamicConfigurationEnough(t *testing.T) {
|
|||
Backends: backends,
|
||||
Servers: servers,
|
||||
},
|
||||
cfg: &Configuration{
|
||||
DynamicCertificatesEnabled: false,
|
||||
},
|
||||
cfg: &Configuration{},
|
||||
}
|
||||
|
||||
newConfig := commonConfig
|
||||
|
@ -95,12 +97,13 @@ func TestIsDynamicConfigurationEnough(t *testing.T) {
|
|||
Backends: []*ingress.Backend{{Name: "a-backend-8080"}},
|
||||
Servers: servers,
|
||||
}
|
||||
|
||||
ngx_config.EnableDynamicCertificates = true
|
||||
|
||||
if !n.IsDynamicConfigurationEnough(newConfig) {
|
||||
t.Errorf("Expected to be dynamically configurable when only backends change")
|
||||
}
|
||||
|
||||
n.cfg.DynamicCertificatesEnabled = true
|
||||
|
||||
newServers := []*ingress.Server{{
|
||||
Hostname: "myapp1.fake",
|
||||
Locations: []*ingress.Location{
|
||||
|
@ -243,7 +246,10 @@ func TestConfigureDynamically(t *testing.T) {
|
|||
ControllerPodsCount: 2,
|
||||
}
|
||||
|
||||
err = configureDynamically(commonConfig, false)
|
||||
ngx_config.EnableDynamicCertificates = false
|
||||
defer func() { ngx_config.EnableDynamicCertificates = true }()
|
||||
|
||||
err = configureDynamically(commonConfig)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error posting dynamic configuration: %v", err)
|
||||
}
|
||||
|
|
|
@ -20,16 +20,14 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"k8s.io/klog"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/file"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
"k8s.io/ingress-nginx/internal/k8s"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/net/ssl"
|
||||
)
|
||||
|
||||
|
@ -103,7 +101,7 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
return nil, fmt.Errorf("unexpected error creating SSL Cert: %v", err)
|
||||
}
|
||||
|
||||
if !s.isDynamicCertificatesEnabled || len(ca) > 0 {
|
||||
if !ngx_config.EnableDynamicCertificates || len(ca) > 0 {
|
||||
err = ssl.StoreSSLCertOnDisk(s.filesystem, nsSecName, sslCert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while storing certificate and key: %v", err)
|
||||
|
@ -152,57 +150,6 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
return sslCert, nil
|
||||
}
|
||||
|
||||
func (s *k8sStore) checkSSLChainIssues() {
|
||||
for _, item := range s.ListLocalSSLCerts() {
|
||||
secrKey := k8s.MetaNamespaceKey(item)
|
||||
secret, err := s.GetLocalSSLCert(secrKey)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if secret.FullChainPemFileName != "" {
|
||||
// chain already checked
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := ssl.FullChainCert(secret.PemFileName, s.filesystem)
|
||||
if err != nil {
|
||||
klog.Errorf("Error generating CA certificate chain for Secret %q: %v", secrKey, err)
|
||||
continue
|
||||
}
|
||||
|
||||
fullChainPemFileName := fmt.Sprintf("%v/%v-%v-full-chain.pem", file.DefaultSSLDirectory, secret.Namespace, secret.Name)
|
||||
|
||||
file, err := s.filesystem.Create(fullChainPemFileName)
|
||||
if err != nil {
|
||||
klog.Errorf("Error creating SSL certificate file for Secret %q: %v", secrKey, err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = file.Write(data)
|
||||
if err != nil {
|
||||
klog.Errorf("Error creating SSL certificate for Secret %q: %v", secrKey, err)
|
||||
continue
|
||||
}
|
||||
|
||||
dst := &ingress.SSLCert{}
|
||||
|
||||
err = mergo.MergeWithOverwrite(dst, secret)
|
||||
if err != nil {
|
||||
klog.Errorf("Error creating SSL certificate for Secret %q: %v", secrKey, err)
|
||||
continue
|
||||
}
|
||||
|
||||
dst.FullChainPemFileName = fullChainPemFileName
|
||||
|
||||
klog.Infof("Updating local copy of SSL certificate %q with missing intermediate CA certs", secrKey)
|
||||
s.sslStore.Update(secrKey, dst)
|
||||
// this update must trigger an update
|
||||
// (like an update event from a change in Ingress)
|
||||
s.sendDummyEvent()
|
||||
}
|
||||
}
|
||||
|
||||
// sendDummyEvent sends a dummy event to trigger an update
|
||||
// This is used in when a secret change
|
||||
func (s *k8sStore) sendDummyEvent() {
|
||||
|
|
|
@ -35,7 +35,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/labels"
|
||||
k8sruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
|
@ -187,8 +186,6 @@ func (i *Informer) Run(stopCh chan struct{}) {
|
|||
|
||||
// k8sStore internal Storer implementation using informers and thread safe stores
|
||||
type k8sStore struct {
|
||||
isOCSPCheckEnabled bool
|
||||
|
||||
// backendConfig contains the running configuration from the configmap
|
||||
// this is required because this rarely changes but is a very expensive
|
||||
// operation to execute in each OnUpdate invocation
|
||||
|
@ -224,24 +221,20 @@ type k8sStore struct {
|
|||
|
||||
defaultSSLCertificate string
|
||||
|
||||
isDynamicCertificatesEnabled bool
|
||||
|
||||
pod *k8s.PodInfo
|
||||
}
|
||||
|
||||
// New creates a new object store to be used in the ingress controller
|
||||
func New(checkOCSP bool,
|
||||
func New(
|
||||
namespace, configmap, tcp, udp, defaultSSLCertificate string,
|
||||
resyncPeriod time.Duration,
|
||||
client clientset.Interface,
|
||||
fs file.Filesystem,
|
||||
updateCh *channels.RingChannel,
|
||||
isDynamicCertificatesEnabled bool,
|
||||
pod *k8s.PodInfo,
|
||||
disableCatchAll bool) Storer {
|
||||
|
||||
store := &k8sStore{
|
||||
isOCSPCheckEnabled: checkOCSP,
|
||||
informers: &Informer{},
|
||||
listers: &Lister{},
|
||||
sslStore: NewSSLCertTracker(),
|
||||
|
@ -252,7 +245,6 @@ func New(checkOCSP bool,
|
|||
backendConfigMu: &sync.RWMutex{},
|
||||
secretIngressMap: NewObjectRefMap(),
|
||||
defaultSSLCertificate: defaultSSLCertificate,
|
||||
isDynamicCertificatesEnabled: isDynamicCertificatesEnabled,
|
||||
pod: pod,
|
||||
}
|
||||
|
||||
|
@ -878,10 +870,6 @@ func (s *k8sStore) setConfig(cmap *corev1.ConfigMap) {
|
|||
func (s *k8sStore) Run(stopCh chan struct{}) {
|
||||
// start informers
|
||||
s.informers.Run(stopCh)
|
||||
|
||||
if s.isOCSPCheckEnabled {
|
||||
go wait.Until(s.checkSSLChainIssues, 60*time.Second, stopCh)
|
||||
}
|
||||
}
|
||||
|
||||
// GetRunningControllerPodsCount returns the number of Running ingress-nginx controller Pods
|
||||
|
|
|
@ -41,6 +41,7 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/file"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/k8s"
|
||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||
)
|
||||
|
@ -87,7 +88,7 @@ func TestStore(t *testing.T) {
|
|||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(true,
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -97,7 +98,6 @@ func TestStore(t *testing.T) {
|
|||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
@ -168,7 +168,7 @@ func TestStore(t *testing.T) {
|
|||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(true,
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -178,7 +178,6 @@ func TestStore(t *testing.T) {
|
|||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
@ -319,7 +318,7 @@ func TestStore(t *testing.T) {
|
|||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(true,
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -329,7 +328,6 @@ func TestStore(t *testing.T) {
|
|||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
@ -426,7 +424,7 @@ func TestStore(t *testing.T) {
|
|||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(true,
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -436,7 +434,6 @@ func TestStore(t *testing.T) {
|
|||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
@ -516,7 +513,7 @@ func TestStore(t *testing.T) {
|
|||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(true,
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -526,7 +523,6 @@ func TestStore(t *testing.T) {
|
|||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
@ -628,7 +624,7 @@ func TestStore(t *testing.T) {
|
|||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(true,
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
fmt.Sprintf("%v/tcp", ns),
|
||||
|
@ -638,7 +634,6 @@ func TestStore(t *testing.T) {
|
|||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
false,
|
||||
pod,
|
||||
false)
|
||||
|
||||
|
@ -708,6 +703,9 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("should exists a secret in the local store and filesystem", func(t *testing.T) {
|
||||
ngx_config.EnableDynamicCertificates = false
|
||||
defer func() { ngx_config.EnableDynamicCertificates = true }()
|
||||
|
||||
err := framework.WaitForSecretInNamespace(clientSet, ns, name)
|
||||
if err != nil {
|
||||
t.Errorf("error waiting for secret: %v", err)
|
||||
|
|
|
@ -32,9 +32,6 @@ type SSLCert struct {
|
|||
CAFileName string `json:"caFileName"`
|
||||
// PemFileName contains the path to the file with the certificate and key concatenated
|
||||
PemFileName string `json:"pemFileName"`
|
||||
// FullChainPemFileName contains the path to the file with the certificate and key concatenated
|
||||
// This certificate contains the full chain (ca + intermediates + cert)
|
||||
FullChainPemFileName string `json:"fullChainPemFileName"`
|
||||
// PemSHA contains the sha1 of the pem file.
|
||||
// This is used to detect changes in the secret that contains the certificates
|
||||
PemSHA string `json:"pemSha"`
|
||||
|
|
|
@ -523,9 +523,6 @@ func (s1 *SSLCert) Equal(s2 *SSLCert) bool {
|
|||
if !s1.ExpireTime.Equal(s2.ExpireTime) {
|
||||
return false
|
||||
}
|
||||
if s1.FullChainPemFileName != s2.FullChainPemFileName {
|
||||
return false
|
||||
}
|
||||
if s1.PemCertKey != s2.PemCertKey {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/ingress-nginx/internal/file"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/watch"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
@ -74,8 +75,18 @@ func verifyPemCertAgainstRootCA(pemCert *x509.Certificate, ca []byte) error {
|
|||
// CreateSSLCert validates cert and key, extracts common names and returns corresponding SSLCert object
|
||||
func CreateSSLCert(cert, key []byte) (*ingress.SSLCert, error) {
|
||||
var pemCertBuffer bytes.Buffer
|
||||
|
||||
pemCertBuffer.Write(cert)
|
||||
|
||||
if ngx_config.EnableSSLChainCompletion {
|
||||
data, err := fullChainCert(cert)
|
||||
if err != nil {
|
||||
klog.Errorf("Error generating certificate chain for Secret: %v", err)
|
||||
} else {
|
||||
pemCertBuffer.Reset()
|
||||
pemCertBuffer.Write(data)
|
||||
}
|
||||
}
|
||||
|
||||
pemCertBuffer.Write([]byte("\n"))
|
||||
pemCertBuffer.Write(key)
|
||||
|
||||
|
@ -376,7 +387,6 @@ func GetFakeSSLCert(fs file.Filesystem) *ingress.SSLCert {
|
|||
}
|
||||
|
||||
func getFakeHostSSLCert(host string) ([]byte, []byte) {
|
||||
|
||||
var priv interface{}
|
||||
var err error
|
||||
|
||||
|
@ -423,16 +433,11 @@ func getFakeHostSSLCert(host string) ([]byte, []byte) {
|
|||
return cert, key
|
||||
}
|
||||
|
||||
// FullChainCert checks if a certificate file contains issues in the intermediate CA chain
|
||||
// fullChainCert checks if a certificate file contains issues in the intermediate CA chain
|
||||
// Returns a new certificate with the intermediate certificates.
|
||||
// If the certificate does not contains issues with the chain it return an empty byte array
|
||||
func FullChainCert(in string, fs file.Filesystem) ([]byte, error) {
|
||||
data, err := fs.ReadFile(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cert, err := certUtil.DecodeCertificate(data)
|
||||
func fullChainCert(in []byte) ([]byte, error) {
|
||||
cert, err := certUtil.DecodeCertificate(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -452,11 +457,6 @@ func FullChainCert(in string, fs file.Filesystem) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
certs, err = certUtil.AddRootCA(certs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return certUtil.EncodeCertificates(certs), nil
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ http {
|
|||
end
|
||||
{{ end }}
|
||||
|
||||
{{ if $all.DynamicCertificatesEnabled }}
|
||||
{{ if $all.EnableDynamicCertificates }}
|
||||
ok, res = pcall(require, "certificate")
|
||||
if not ok then
|
||||
error("require failed: " .. tostring(res))
|
||||
|
@ -492,13 +492,8 @@ http {
|
|||
# PEM sha: {{ $redirect.SSLCert.PemSHA }}
|
||||
ssl_certificate {{ $redirect.SSLCert.PemFileName }};
|
||||
ssl_certificate_key {{ $redirect.SSLCert.PemFileName }};
|
||||
{{ if not (empty $redirect.SSLCert.FullChainPemFileName)}}
|
||||
ssl_trusted_certificate {{ $redirect.SSLCert.FullChainPemFileName }};
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
{{ end }}
|
||||
|
||||
{{ if $all.DynamicCertificatesEnabled}}
|
||||
{{ if $all.EnableDynamicCertificates}}
|
||||
ssl_certificate_by_lua_block {
|
||||
certificate.call()
|
||||
}
|
||||
|
@ -841,13 +836,8 @@ stream {
|
|||
# PEM sha: {{ $server.SSLCert.PemSHA }}
|
||||
ssl_certificate {{ $server.SSLCert.PemFileName }};
|
||||
ssl_certificate_key {{ $server.SSLCert.PemFileName }};
|
||||
{{ if not (empty $server.SSLCert.FullChainPemFileName)}}
|
||||
ssl_trusted_certificate {{ $server.SSLCert.FullChainPemFileName }};
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
{{ end }}
|
||||
|
||||
{{ if $all.DynamicCertificatesEnabled}}
|
||||
{{ if $all.EnableDynamicCertificates}}
|
||||
ssl_certificate_by_lua_block {
|
||||
certificate.call()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue