Mixed Content error nginx ingress in kubernetes for rails app
Asked Answered
B

1

10

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
Beltane answered 28/12, 2017 at 5:17 Comment(0)
T
2

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.

Transmit answered 31/12, 2017 at 14:5 Comment(1)
use_ssl is being called in the params and it still seems to not wanna workBeltane

© 2022 - 2024 — McMap. All rights reserved.