Need to help on routing https URL with redirectpath - kubernetes

I am running Nginx ingress inside one of our EKS cluster and earlier had issue to http-->https redirect as we are terminating SSL at AWS NLB. I was able to get it fixed using the method listed in this ticket https://github.com/kubernetes/ingress-nginx/issues/2724 ( Thanks to #Ariseaz )
However, along with https redirect we want to append path and redirect which is not working. Here are some methods I have tried so far
The container webpage serving paths /coffee and /tea
http://cafe.com ------> https://cafe.com ## This works because of the http --> https redirection
http://cafe.com/tea -----> https://cafe.com/tea ## This works
http://cafe.com/coffee -----> https://cafe.com/coffee ## This works
Now when I want to redirect https://cafe.com to https://cafe/coffee it does not work.
Can anyone please tell me now to append path to https:hostname and redirect.. I was able-to get is working with AWS ALB Ingress with this annotation and I am trying to get the same method with nginx ingress.
alb.ingress.kubernetes.io/actions.svc-cafe: >
{"Type":"redirect","RedirectConfig":{"Path":"/coffee","Protocol":"HTTPS", "Port": "443","StatusCode":"HTTP_301"}} ## This is to append /coffee to hostname and redirect ( https://cafe.com ---> htttps://cafe.com/coffee)
Here is my ingress file using Nginx ingress controller
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cafe-example
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
if ($host = "https://cafe.com") {
return 301 https://$host$request_uri/coffee;
}
#nginx.ingress.kubernetes.io/rewrite-target: /
#nginx.ingress.kubernetes.io/configuration-snippet: |
# rewrite ^(/coffee)$ $1/ permanent;
spec:
ingressClassName: internal-nginx
rules:
- host: cafe.com
http:
paths:
- path: /tea
pathType: Prefix
backend:
service:
name: tea-svc
port:
number: 80
- path: /coffee
pathType: Prefix
backend:
service:
name: coffee-svc
port:
number: 80

Please try :
nginx.ingress.kubernetes.io/server-snippet: |
if ($host ~ "https://cafe.com")
{
rewrite ^ https://$host$request_uri/coffee permanent;
}
or else try
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'https://cafe.com' ) {
return 301 https://$host$request_uri/coffee;
}

When I change the host to cafe.com instead of https://cafe.com I can see it the url getting redirected but its going in a loop
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'cafe.com' ) {
return 301 https://$host$request_uri/coffee;
}
https://cafe.com//coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee/coffee

You can try this
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'cafe.com' ) {
return 301 https://cafe.com/coffee;
}
OR
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'cafe.com' ) {
rewrite ^([^.]*[^/])$ https://cafe.com/coffee permanent;
}

Related

Redirect from www to non www duplicates query params kubernetes

I am trying to redirect from https://example.nl to https://www.example.nl. This works perfectly. However, when I add query params, the query params get duplicated.
For example, whenever I go to example.nl?test=a, it redirects to wwww.example.nl?test=a?test=a.
How do I prevent this duplication of query params?
I use kubernetes and digital ocean. My kubernetes ingress file looks as follows:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
service.beta.kubernetes.io/do-loadbalancer-name: "example"
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/backend-protocol: HTTP
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'example.nl' ) {
rewrite ^ https://www.example.nl$request_uri permanent;
}
nginx.ingress.kubernetes.io/server-snippet: |
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/svg+xml
text/css
text/javascript
text/plain
text/xml;
spec:
tls:
- hosts:
- www.example.nl
- example.nl
secretName: main-example-tls
rules:
- host: www.example.nl
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: front-end
port:
number: 3000
- path: /api
pathType: Prefix
backend:
service:
name: back-end
port:
number: 8000
- host: example.nl
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: front-end
port:
number: 3000
- path: /api
pathType: Prefix
backend:
service:
name: back-end
port:
number: 8000
If any additional informations is required. Please let me know.
try something like
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite / https://test.app.example.com$uri permanent;
You can also refer my article : https://medium.com/#harsh.manvar111/kubernetes-ingress-domain-redirect-4595e9030a2c

Ensure ingress rule creation

My problem: i create ingress rule via kubernetes-client:
try (InputStream is = IOUtils.toInputStream(crd, StandardCharsets.UTF_8)) {
client.load(is).inNamespace(namespaceName).createOrReplace();
}
Where is - yaml file with ingress rule like:
spec:
ingressClassName: nginx
rules:
- host: {{host}}
http:
paths:
- backend:
service:
name: {{service_name}}
port:
number: 80
path: /
pathType: ImplementationSpecific
But in my task i need ensure that the rule is created, i need wait or check status in loop.
What is the best way to do it?
Thanx!
I think you might be able to do it with waitUntilCondition:
try (KubernetesClient client = new KubernetesClientBuilder().build()) {
Ingress ingress = client.network().v1().ingresses()
.load(IngressRuleWaitUntilCondition.class.getResourceAsStream("/ingress-rule.yml"))
.get();
client.resource(ingress)
.inNamespace("default")
.createOrReplace();
client.network().v1()
.ingresses()
.inNamespace("default")
.resource(ingress)
.waitUntilCondition(i -> !i.getSpec().getRules().isEmpty(), 2, TimeUnit.MINUTES);
}

How to deny path in k8S ingress

I would like to block /public/configs in my k8s ingress.
My current settings doesnt work.
- host: example.com
http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: service-myapp
port:
number: 80
- path: /public/configs
pathType: ImplementationSpecific
backend:
service:
name: service-myapp
port:
number: 88 // fake port
Is there any better (easy) way?
1- Create a dummy service and send it to that:
- path: /public/configs
pathType: ImplementationSpecific
backend:
service:
name: dummy-service
port:
number: 80
2- use server-snippets as bellow to return 403 or any error you want:
a) for k8s nginx ingress:
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
location ~* "^/public/configs" {
deny all;
return 403;
}
b) for nginx ingress:
annotations:
nginx.org/server-snippet: |
location ~* "^/public/configs" {
deny all;
return 403;
}

Setting up kubernets Ingress proxy-body-size based on request method

I've been trying to set up a max body size in the Ingress controller based on the HTTP method of a given path.
Basically the POST method should allow 3m as max size and all the other methods should allow 1m.
Right now my main idea was to do something like:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-custom-service
namespace: development
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
kubernetes.io/ingress.class: "nginx-dev"
nginx.ingress.kubernetes.io/configuration-snippet: |
internal;
rewrite ^ $original_uri break;
nginx.ingress.kubernetes.io/server-snippet: |
location /api/v1/my-endpoint {
if ( $request_method = POST) {
set $target_destination '/_post';
client_max_body_size 3M;
}
if ( $request_method != POST) {
set $target_destination '/_not_post';
client_max_body_size 1M;
}
set $original_uri $uri;
rewrite ^ $target_destination last;
}
spec:
tls:
rules:
- host: my-host.com
http:
paths:
- path: /_post
backend:
serviceName: my-service
servicePort: 8080
- path: /_not_post
backend:
serviceName: my-service
servicePort: 8080
But then I'm getting the following error in the pod:
Is there any way I can correctly set-up the max body size via the ingress controller?
Try changing your annotations with the configuration-snippet
nginx.ingress.kubernetes.io/configuration-snippet: |
location /upload-path {
client_max_body_size 8M;
}
Read more at : https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#configuration-snippet

can ingress rewrite 405 to the origin url and change the http-errors 405 to 200?

Can ingress rewrite 405 to the origin url and change the http-errors 405 to 200?
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- http:
paths:
- path: /page/user/(.*)
pathType: Prefix
backend:
serviceName: front-user
servicePort: 80
- path: /page/manager/(.*)
pathType: Prefix
backend:
serviceName: front-admin
servicePort: 80
Ngnix can realize that visit a html page by a post method but I want to know how to realize by ingress.
server {
listen 80;
# ...
error_page 405 =200 #405;
location #405 {
root /srv/http;
proxy_method GET;
proxy_pass http://static_backend;
}
}
This is an e.g. that ngnix realize that visit a html page by a post method to change 405 to 200 and change the method to get
You can use server snippet annotation to achieve it.
Also I rewrote your ingress from extensions/v1beta1 apiVersion to networking.k8s.io/v1, because starting kubernetes v1.22 previous apiVersion is be removed:
$ kubectl apply -f ingress-snippit.yaml
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
Ingress-snippet-v1.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/server-snippet: | # adds this block to server
error_page 405 =200 #405;
location #405 {
root /srv/http;
proxy_method GET;
proxy_pass http://static_backend; # tested with IP since I don't have this upstream
}
spec:
rules:
- http:
paths:
- path: /page/user/(.*)
pathType: Prefix
backend:
service:
name: front-user
port:
number: 80
- path: /page/manager/(.*)
pathType: Prefix
backend:
service:
name: front-admin
port:
number: 80
Applying manifest above and verifying /etc/nginx/nginx.conf in ingress-nginx-controller pod:
$ kubectl exec -it ingress-nginx-controller-xxxxxxxxx-yyyy -n ingress-nginx -- cat /etc/nginx/nginx.conf | less
...
## start server _
server {
server_name _ ;
listen 80 default_server reuseport backlog=4096 ;
listen 443 default_server reuseport backlog=4096 ssl http2 ;
set $proxy_upstream_name "-";
ssl_certificate_by_lua_block {
certificate.call()
}
# Custom code snippet configured for host _
error_page 405 =200 #405;
location #405 {
root /srv/http;
proxy_method GET;
proxy_pass http://127.0.0.1; # IP for testing purposes
}
location ~* "^/page/manager/(.*)" {
set $namespace "default";
set $ingress_name "frontend-ingress";
set $service_name "front-admin";
set $service_port "80";
set $location_path "/page/manager/(.*)";
set $global_rate_limit_exceeding n;
...