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