-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Lua module to serve SSL Certificates dynamically #2965
Add Lua module to serve SSL Certificates dynamically #2965
Conversation
Interesting. Could this mechanism also be used to support having a CA specified in the ingress to be used when communicating with the backend service? |
d00509c
to
78d132f
Compare
BeforeEach(func() { | ||
err := enableDynamicCertificates(f.IngressController.Namespace, f.KubeClientSet) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's also assert here that dynamic certificate feature is indeed enabled:
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "ssl_certificate_by_lua_block") &&
strings.Contains(cfg, "certificate.call()")
})
Expect(err).NotTo(HaveOccurred())
test/e2e/lua/dynamic_certificates.go
Outdated
return framework.UpdateDeployment(kubeClientSet, namespace, "nginx-ingress-controller", 1, | ||
func(deployment *appsv1beta1.Deployment) error { | ||
args := deployment.Spec.Template.Spec.Containers[0].Args | ||
args = append(args, "--enable-dynamic-configuration") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for this, it's enabled by default
rootfs/etc/nginx/lua/certificate.lua
Outdated
|
||
local pem_cert_key = configuration.get_pem_cert_key(hostname) | ||
if not pem_cert_key then | ||
ngx.log(ngx.ERR, "Certificate not found for the given hostname: " .. hostname) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hostname needs to be casted to string, otherwise when it is nil
it will error
test/e2e/lua/dynamic_certificates.go
Outdated
Set("Host", ingress.Spec.TLS[0].Hosts[0]). | ||
TLSClientConfig(&tls.Config{ | ||
InsecureSkipVerify: true, | ||
}). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since you are providing a custom config you have to explicitly set the ServerName
to ingress.Spec.TLS[0].Hosts[0]
test/e2e/lua/dynamic_certificates.go
Outdated
return err | ||
} | ||
|
||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can remove this all if stuff and do return err
07409ba
to
3b92465
Compare
test/e2e/lua/dynamic_certificates.go
Outdated
Hosts: []string{"foo.com"}, | ||
SecretName: "foo.com", | ||
}, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is redundant, when creating Ingress the framework already does this
As discussed IRL this as is won't work since we don't consistently fallback to default certificate when secret is missing and end up configuring HTTP only server even though TLS is included in the Ingress manifest. I created #2972 to fix this. That PR also has more info on why we need that change. |
18b6839
to
153382f
Compare
6da4110
to
cbf041f
Compare
Codecov Report
@@ Coverage Diff @@
## master #2965 +/- ##
==========================================
- Coverage 47.54% 47.52% -0.02%
==========================================
Files 77 77
Lines 5639 5639
==========================================
- Hits 2681 2680 -1
- Misses 2605 2607 +2
+ Partials 353 352 -1
Continue to review full report at Codecov.
|
There are quite a bit of repetition in e2e test implementation but that can be iterated later |
/hold cancel |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ElvinEfendi, hnrytrn The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@kfox1111 are you asking if we can dynamically controler |
@hnrytrn according to the documentation (https://github.com/Shopify/ingress/blob/master/docs/user-guide/cli-arguments.md) this feature is capable of storing roughly 5000 certificates:
Can you explain to me how you came to the max of 5000 certificates? What is the limiting factor? |
hey @discostur , we use Lua shared dictionary (with fixed size) to store the certificates in memory. You can find the configuration at
Do you need to be able to handle more certificates? |
@ElvinEfendi thanks for the explanation. Yes indeed we ware actually trying to put up to 100.000 vhosts / certificates into nginx ingress. If it is only dependent from the storage setting, would it be an idea to make this setting configurable? |
@discostur it would definitely make sense to make it configurable. We can introduce a new configmap key for that. I'd be happy to review if you make a PR. |
@ElvinEfendi yes. securing the communications channel between ingress nginx to the service via the ca used to sign the services certificate. Each service could have its own ca, so should be able to be specified individually in the ingress. something like cert-manager could be used to provision all the service certs easily. Just no way currently to plumb it all together. |
Why not have intermediate CA and issue the certificates for the services using the intermediate CA? This way you can install only that CA in the ingress-nginx. -- But yeah to answer your question, no dynamically configuring |
That could be done. but then puts somewhat of the onus on managing the ca for the entire cluster, which is quite hard. If you could specify what ca to use per service, the service could make up one on the fly and fairly transparently, but it still would be secure from other folks on the same cluster. Just looking for ways of making security easier so folks do it. Ideally fully automatable, so they don't have to think about it at all. :) |
the nginx.ingress.kubernetes.io/secure-verify-ca-secret: "my-ca-secret" code looks like it just about would do what we want. Not sure if it works anymore. Its not documented and there was a closed pr against it. |
What this PR does / why we need it:
This PR ties in #2889 and #2923 to add dynamic certificate serving functionality. When
enable-dynamic-certificates
is on, SSL Certificates won't be written on disk, and will be served dynamically from the shared Lua dictionary using OpenResty's SSL library (https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md), which will avoid reloading NGINX. This PR also adds in E2E tests for the dynamic certificates functionality.