Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed Content error nginx ingress in kubernetes for rails app

Deploying Portus in GCP with an Nginx Ingress load balancer implemented. Portus loads up just fine but when trying to use the application and fill out some of the forms I get the following error:

VM798:1 Mixed Content: The page at 'https://staging.foo.bar/admin/registries/new' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://staging.foo.bar//api/v1/registries/validate?name=devreg&hostname=staging-foo-barregistry%3A5000&external_hostname=&use_ssl=false&force=false&only%5B%5D=hostname'. This request has been blocked; the content must be served over HTTPS.

Nginx configuration: https://github.com/kubic-project/caasp-services/blob/master/contrib/helm-charts/portus/templates/nginx-configmap.yaml

Environment:

  • Kubernetes in GCP
  • all resources deployed through helm
  • ssl is provided by kube-lego
  • Rails app with Grape API gem
  • Grape mounts the api as follows: mount API::RootAPI => "/"

So I've made sure to check the code for manual http calls and didn't see anything. And I've spent a day now trying to dig through rails docs and nginx docs to see what is causing some of the app to load properly with ssl and the API to not follow the same rules

----- Update 1 ------ Upon further investigation, It looks like it has something to do with Vue validator. Checking the developer tools revealed the following:

curl 'http://staging.foo.bar//api/v1/registries/validate?name=devreg&hostname=st&external_hostname=&use_ssl=false&force=false&only%5B%5D=name' -X OPTIONS -H 'Access-Control-Request-Method: GET' -H 'Origin: https://staging.foo.bar' -H 'Access-Control-Request-Headers: x-csrf-token' --compressed

And it looks like the root url is being called here:

javascript:
      window.API_ROOT_URL = '#{root_url}';

root_url is set to / as mentioned above.

However, analyzing the Vue code closer revels:

Vue.http.options.root = window.API_ROOT_URL;

Vue.http.interceptors.push((_request, next) => {
  window.$.active = window.$.active || 0;
  window.$.active += 1;

  next(() => {
    window.$.active -= 1;
  });
});

Vue.http.interceptors.push((request, next) => {
  if ($.rails) {
    // eslint-disable-next-line no-param-reassign
    request.headers.set('X-CSRF-Token', $.rails.csrfToken());
  }
  next();
});

// we are not a SPA and when user clicks on back/forward
// we want the page to be fully reloaded to take advantage of
// the url query params state
window.onpopstate = function (e) {
  // phantomjs seems to trigger an oppopstate event
  // when visiting pages, e.state is always null and
  // in our component we set an empty string
  if (e.state !== null) {
    window.location.reload();
  }
};

Vue.config.productionTip = process.env.NODE_ENV !== 'production';

Params are set to use SSL in the query

params do
          requires :name,
                   using: API::Entities::Registries.documentation.slice(:name)
          requires :hostname,
                   using: API::Entities::Registries.documentation.slice(:hostname)
          optional :external_hostname,
                   using: API::Entities::Registries.documentation.slice(:external_hostname)
          requires :use_ssl,
                   using: API::Entities::Registries.documentation.slice(:use_ssl)
          optional :only, type: Array[String]
        end
like image 900
niharvey Avatar asked Dec 28 '17 05:12

niharvey


People also ask

What is pathType ImplementationSpecific?

Path types ImplementationSpecific : With this path type, matching is up to the IngressClass. Implementations can treat this as a separate pathType or treat it identically to Prefix or Exact path types. Exact : Matches the URL path exactly and with case sensitivity.

Does Kubernetes ingress use nginx?

ingress-nginx is an Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer. Learn more about Ingress on the main Kubernetes documentation site.


1 Answers

I'm not sure about how your app works, and the mechanics of what data is being passed where, but I suspect you might need to be passing use_ssl=true in the querystring parameter to your /validate endpoint.

Currently, use_ssl=false is being passed, which is likely returning a non-SSL response.

like image 148
grizzthedj Avatar answered Sep 29 '22 12:09

grizzthedj