Skip to content
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

Server-only authentication of backends and per-location SSL config #4689

Merged
merged 2 commits into from Nov 19, 2019

Conversation

janosi
Copy link
Contributor

@janosi janosi commented Oct 17, 2019

What this PR does / why we need it:

  1. It enables the one-way authentication of backends based on the ca.crt configured in the annotation proxy-ssl-secret.
  2. It enables the configuration of different proxy-ssl-secrets for the different locations of the same server

Which issue this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close that issue when PR gets merged): fixes #4688 #4503

Special notes for your reviewer:

…server but with own unique Ingress definitions can have different SSL configs
@k8s-ci-robot
Copy link
Contributor

Welcome @janosi!

It looks like this is your first PR to kubernetes/ingress-nginx 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes/ingress-nginx has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Oct 17, 2019
@k8s-ci-robot
Copy link
Contributor

Hi @janosi. Thanks for your PR.

I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Oct 17, 2019
@aledbf
Copy link
Member

aledbf commented Oct 17, 2019

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Oct 17, 2019
@codecov-io
Copy link

codecov-io commented Oct 17, 2019

Codecov Report

Merging #4689 into master will decrease coverage by 0.02%.
The diff coverage is 33.33%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4689      +/-   ##
==========================================
- Coverage   58.62%   58.59%   -0.03%     
==========================================
  Files          88       88              
  Lines        6743     7057     +314     
==========================================
+ Hits         3953     4135     +182     
- Misses       2353     2443      +90     
- Partials      437      479      +42
Impacted Files Coverage Δ
internal/ingress/controller/store/store.go 58.51% <0%> (-0.13%) ⬇️
internal/ingress/controller/store/backend_ssl.go 42.85% <0%> (-0.45%) ⬇️
internal/ingress/controller/controller.go 53.42% <100%> (+2.98%) ⬆️
...nternal/ingress/annotations/secureupstream/main.go 91.66% <0%> (-8.34%) ⬇️
internal/watch/file_watcher.go 80.76% <0%> (-3.85%) ⬇️
internal/ingress/zz_generated.deepcopy.go 0% <0%> (ø) ⬆️
internal/ingress/types.go 0% <0%> (ø) ⬆️
internal/ingress/metric/collectors/process.go 90.42% <0%> (+2.12%) ⬆️
internal/ingress/types_equals.go 23.73% <0%> (+6.34%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 43fa61c...cc84bd4. Read the comment docs.

@aledbf
Copy link
Member

aledbf commented Oct 17, 2019

/retest

@janosi
Copy link
Contributor Author

janosi commented Oct 18, 2019

/assign @bowei

@@ -491,17 +491,6 @@ func (n *NGINXController) getBackendServers(ingresses []*ingress.Ingress) ([]*in
server.Hostname, ingKey)
}

if server.ProxySSL.CAFileName == "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you removing this?
Without it, you can overwrite the server certificate, if the annotation is used in two different Ingress rules for the same hostname.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly that is the purpose here. The intent is to move the proxy-ssl rules to location level instead of the current server level. So users can then define certificates on location (backend/service) level. I.e. the different locations under the same server can have different certificates. This is an ingress usage pattern in our cloud.

@@ -104,17 +104,19 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
return nil, fmt.Errorf("unexpected error creating SSL Cert: %v", err)
}

path, err := ssl.StoreSSLCertOnDisk(nsSecName, sslCert)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you doing this?
Only CA certificates should be stored on disk. Everything else is handled by Lua, dynamically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I used the original version and I defined proxy-ssl-secret in my Ingress the result was a config file in which all of these: proxy_ssl_trusted_cert, proxy_ssl_certificate, proxy_ssl_certificate_key pointed to the same file on disk. It was my experience with the original version. I.e. it wanted to have the tls.crt and tls.key from a file on a disk originally.
If I understand the original code well it does the following: puts the client cert and key into sslCert, then if server CA is present then it first stores the sslCert (i.e. client key and cert) on disk first, then it appends the server CA to the file.
In order to preserve this function I kept the writing the client key and cert to disk in my code. I tested it, it works. Both when there is only ca.crt in the proxy-ssl-secret, and also when there are additional tls.key and tls.crt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aledbf I would like to ask, could you please help me in finding that lua script that is supposed to manage the client key and cert? I would like to see the whole picture (even though my experience with the original version showed that the controller configured nginx to take those from the CAFile from disk) Thank you!

@janosi
Copy link
Contributor Author

janosi commented Oct 25, 2019

@aledbf Is there anything I can do for this PR?

@aledbf
Copy link
Member

aledbf commented Oct 25, 2019

Is there anything I can do for this PR?

Don't break the current behavior. I understand your goal here but this change will break existing ingresses after an upgrade.

@janosi
Copy link
Contributor Author

janosi commented Oct 25, 2019

@aledbf
I do not think it breaks any behavior. The proxy-ssl parameters are moved to the location level from server level, but those are still there and applied on every location under the same server. I.e .the functionality is the same.
Also about the storing the secrets on disk: it is not new here, the only thing I did is that I moved the disk writing out from the condition that checks whether the ca.crt is available or not (and I think ca.crt is always available, as that is a must for the minimal server/backend authentication - so the tls.key and tls.crt were always written to disk in reality). So, writing the tls.key and tls.crt to disk is not a new thing that I introduced here.
Please help me in understanding what it breaks from functionality perspective.
One scenario I can imagine: someone has 2 Ingresses, that both points to the same host but different paths. In one of them she defines proxy-ssl-secret, but not in the other one. And as the result all the locations are actually under the same proxy-ssl parameters (because of the common host/server).
With this change she should put the proxy-ssl-secret into both Ingress definitions to get to the same goal.
Though, personally, if I define an Ingress with proxy-ssl-secret, and another Ingress without proxy-ssl-secret I would not expect that the proxy-ssl parameters are applied also on the 2nd one due to the first Ingress . In order to expect such behavior there should be a confirmed hierarchical dependency among Ingresses, i.e. when the parameters of an Ingress are inherited into another Ingress- which is not true for the current Ingress resource in k8s.
On the other hand it fixes the problem that people currently cannot use one-way auth to the backends, and that people currently cannot have different secrets for the different paths.

@janosi
Copy link
Contributor Author

janosi commented Oct 26, 2019

@aledbf I restored the functionality that puts the proxy_ssl parameters on server level. I.e. the old functionality is restored. Beside that the new logic puts the proxy_ssl parameters to location level, too.
Luckily if both a server and a corresponding location have proxy_ssl parameters the parameters of the location are taken into account - i.e. the missing/incorrect functionality is fixed now, while preserving the old logic.
Also the logic that writes secrets to the disk is restored now.
Please check.

…mments received.

Also writing tls.crt and tls.key to disk is according to the original code.
@k8s-ci-robot k8s-ci-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Oct 26, 2019
@janosi
Copy link
Contributor Author

janosi commented Oct 29, 2019

@aledbf Could you please check and comment? Thank you!

@janosi
Copy link
Contributor Author

janosi commented Nov 1, 2019

@aledbf @ElvinEfendi Could any of you please check this? Thank you!

@aledbf aledbf added this to In Progress in 0.27.0 Nov 8, 2019
@aledbf
Copy link
Member

aledbf commented Nov 19, 2019

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 19, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: aledbf, janosi

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 19, 2019
@k8s-ci-robot k8s-ci-robot merged commit 62518b6 into kubernetes:master Nov 19, 2019
@aledbf aledbf moved this from In Progress to done in 0.27.0 Nov 19, 2019
@janosi janosi deleted the upstream_ssl branch November 19, 2019 07:45
@janosi
Copy link
Contributor Author

janosi commented Nov 19, 2019

@aledbf Thank you!

@EronWright
Copy link

EronWright commented Mar 16, 2022

For those who find themselves here, this PR does make it possible to use a secret containing only a CA certificate bundle, as referenced by the nginx.ingress.kubernetes.io/proxy-ssl-secret annotation. Thanks again @janosi!

apiVersion: v1
kind: Secret
metadata:
  name: proxy-ssl-secret
data:
  ca.crt: (base64-encoded PEM file)
type: Opaque

The set of annotations that worked for me to use an HTTPS backend:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS"
    "nginx.ingress.kubernetes.io/proxy-ssl-secret": "ingress-nginx/ingress-nginx-proxy-ssl-secret"
    "nginx.ingress.kubernetes.io/proxy-ssl-verify": "on"
    "nginx.ingress.kubernetes.io/proxy-ssl-server-name": "on"
    "nginx.ingress.kubernetes.io/proxy-ssl-name": "backend.example"
    "nginx.ingress.kubernetes.io/upstream-vhost": "backend.example"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.
Projects
No open projects
0.27.0
  
done
Development

Successfully merging this pull request may close these issues.

TLS to backends - server-only authentication and per-location SSL config
6 participants