Istio Virtual Service - Proxy to external HTTPS service - nexus

I'm trying to proxy HTTP requests with specified URI prefix to an external HTTPS server.
The idea is to use ower internal Nexus Repository manager for NPM, but don't loosethe ability for 'npm audit' like this project does GitHub Project. It should be done with Istio instead of deploying an extra app.
I configured a virtual service and a service entry to route the traffic to the external service. So far it was not possible to convert an HTTP request to an HTTPS request. Is there any chance to do this?
Configuration:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-nexus
spec:
hosts:
- "test.com"
gateways:
- gateway-xy
http:
- match:
- uri:
prefix: /-/npm/v1/security/audits/
route:
- destination:
port:
number: 443
host: registry.npmjs.org
- route:
- destination:
port:
number: 80
host: nexus
---
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: npmjs-ext
spec:
hosts:
- registry.npmjs.org
ports:
- number: 443
name: tls
protocol: tls
resolution: DNS
location: MESH_EXTERNAL

Found a solution: You need to add an DestinationRule with TLS mode 'SIMPLE' to connect to an external HTTPS service.
The whole configuration for my issue with forwarding 'npm audit' requests to public 'registry.npmjs.org', if you are using a private Nexus Repository is:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs
spec:
hosts:
- "test.com"
gateways:
- gateway
http:
# Route to npm registry for audit
# Like this: https://github.com/chovyy/npm-audit-proxy
# See: https://istio.io/latest/blog/2019/proxy/
- match:
- uri:
prefix: /-/npm/v1/security
headers:
request:
set:
host: "registry.npmjs.org"
route:
- destination:
port:
number: 443
host: registry.npmjs.org
# This is for custom Nexus repositories: You need to rewrite the route, that the prefix of the repository URL is not forwarded to registry.npmjs.org
- match:
- uri:
prefix: /repository/npm-test-repo/-/npm/v1/security
rewrite:
uri: /-/npm/v1/security
headers:
request:
set:
host: "registry.npmjs.org"
route:
- destination:
port:
number: 443
host: registry.npmjs.org
- route:
- destination:
port:
number: 80
host: nexus
---
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: npmjs-ext
spec:
hosts:
- registry.npmjs.org
ports:
- number: 443
name: tls
protocol: TLS
resolution: DNS
location: MESH_EXTERNAL
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: npmjs-ext
spec:
host: registry.npmjs.org
trafficPolicy:
tls:
mode: SIMPLE

Related

K8S Ingress controller, Cert manager and LetsEncrypt SSL doesn't working

I have created a brand new K8S cluster
I have created the Ingress nginx controller.
The controller created a namespace with all of the required Pods, Svcs and etc.
I have created an Ingress object that routes the traffic to a Deployment service with TLS enabled.
I have created a cluster issuer object.
When inspecting the kubectl describe cert everything okay and ready.
When inspecting the kubectl describe clusterissuer, as well.
When doing curl https://example.com/ it returns the following error:
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
Without SSL, the access is enabled from outside and works properly, when adding back the SSL configuration in the Ingress object, it fails again.
ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- k8s-poc.example.com
secretName: echo-tls
rules:
- host: k8s-poc.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test-svc
port:
number: 3333
test-depl.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-depl
labels:
app: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- name: test
image: mydockeruser/test:42
ports:
- containerPort: 3333
imagePullSecrets:
- name: docker-regcred
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: test-svc
spec:
selector:
app: test
ports:
- name: http
protocol: TCP
port: 3333
targetPort: 3333
prod-issuer.yaml:
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: cert-manager
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: my#email.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx

istio host matching rule redirection problem

I've 2 different services in Kubernetes. My purpose is to open these services and application behind the services to the outside. The problem is that application index.html has a redirection and it causes requests' bypass host matching rules.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: app1-vs
namespace: customapp
spec:
hosts:
- mydomain.com
gateways:
- customapp-gateway
http:
- match:
- uri:
prefix: "/app1"
route:
- destination:
host: app1.customapp.svc.cluster.local
port:
number: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: app2-vs
namespace: customapp
spec:
hosts:
- mydomain.com
gateways:
- customapp-gateway
http:
- match:
- uri:
prefix: "/app2"
route:
- destination:
host: app2.customapp.svc.cluster.local
port:
number: 81
I mean, mydomain.com/app1/index.html forwards requests to mydomain.com/login page which out of matching rule. How can I figure it out?

ISTIO GRPC Gateway configuration

I am trying to setup ISTIO Gateway with GRPC. I am using example from:https://github.com/h3poteto/istio-grpc-example.
This example does not contain Gateway. I added the Gateway:
kind: Gateway
metadata:
name: my-gateway
namespace: istio-grpc-example
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: grpc-wildcard
protocol: GRPC
hosts:
- "*"
and modified the VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: istio-grpc-example
spec:
hosts:
- "backend"
gateways:
- my-gateway
http:
- match:
- port: 50051
route:
- destination:
host: backend
subset: v0
weight: 90
- destination:
host: backend
subset: v1
weight: 10
Is there somethig else I should do? I still cannot go through Gateway… Received an error when querying services endpoint.
Thank you!
As I mentioned in comments
Have you tried with wildcard hosts? * instead of backend?
You need to change virtual service hosts.
spec:
hosts:
- "backend"
to
spec:
hosts:
- "*"
And #Ondra add that other thing he changed was the gateway port number.
I changed the port number from 80 to 31400 and changed the host from "backend" to "*". Now it looks like everything is working. – Ondra

You're speaking plain HTTP to an SSL-enabled server port in Kubernetes

My Gateway file is as
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway-secure
namespace: myapp
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
privateKey: /etc/istio/ingressgateway-certs/tls.key
#caCertificates: /etc/istio/ingressgateway-ca-certs/kbundle.crt
hosts:
- "*"
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-gateway-service-secure
namespace:myapp
spec:
hosts:
- "sub.domaincom"
gateways:
- my-gateway-secure
http:
- route:
- destination:
host: my-mono
port:
number: 443
protocol: TCP
and my service file is
apiVersion: v1
kind: Service
metadata:
name: my-mono
namespace: myapp
labels:
tier: backend
spec:
selector:
app: my-mono
tier: backend
ports:
- port: 443
name: https
protocol: TCP
Deployment file is as
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-mono
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: my-mono
template:
metadata:
labels:
app: my-mono
spec:
containers:
- name: my-mono
image: myapacheimage
imagePullPolicy: Never
ports:
- containerPort: 443
when i access my service using gateway it says
Bad Request
Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.
Apache/2.4.38 (Debian) Server at 10.0.159.77 Port 443
i can confirm that apache is only listening on 443 and is properly configured
Your configuration uses the TLS termination on istio gateway. So the HTTPS traffic entering the istio ingress is decrypted to plain HTTP traffic before reaching Your service endpoint.
To fix this You need to configure HTTPS ingress access to an HTTPS service, i.e., configure an ingress gateway to perform SNI passthrough, instead of TLS termination on incoming requests.
You can find an example of Ingress Gateway without TLS Termination in istio documentation guide here.
Your Gateway and VirtualService should look something like this:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway-secure
namespace: myapp
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: PASSTHROUGH
hosts:
- "*"
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-gateway-service-secure
namespace:myapp
spec:
hosts:
- "sub.domaincom"
gateways:
- my-gateway-secure
tls:
- match:
- port: 443
sni_hosts:
- "sub.domaincom"
route:
- destination:
host: my-mono
port:
number: 443
Hope it helps.

Port based routing in Istio with GRPC service on GKE Not Working

We are running GRPC services on Google Kubernetes Engine with Istio. We have done following setup for the request routing which is not working.
We are receiving following error while making GRPC call to service :
upstream connect error or disconnect/reset before headers
Please let me know if there is missing something or there is workaround.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 50051
name: grpc
protocol: GRPC
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld
spec:
hosts:
- "*"
gateways:
- helloworld-gateway
http:
- match:
- port: 50051
route:
- destination:
host: helloworld
port:
number: 50051

Resources