Skip to content

Commit

Permalink
Support deployment behind NGINX reverse proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
enricovianello committed Mar 19, 2024
1 parent bb5aa0a commit a64790d
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 6 deletions.
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# https://spring.io/guides/topicals/spring-boot-docker#_multi_stage_build
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
RUN apk add maven
COPY pom.xml .
COPY maven maven
RUN mvn dependency:resolve -s maven/cnaf-mirror-settings.xml
RUN mvn dependency:resolve-plugins -s maven/cnaf-mirror-settings.xml
COPY .git .git
COPY etc etc
COPY src src
RUN mvn package -s maven/cnaf-mirror-settings.xml -Dmaven.test.skip
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
COPY src src
EXPOSE 8086
ENTRYPOINT ["java","-Dspring.profiles.active=dev","-cp","app:app/lib/*","org.italiangrid.storm.webdav.WebdavService"]
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
podman build -t storm-webdav .
33 changes: 33 additions & 0 deletions compose-nginx/assets/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
user nobody;
worker_processes 1;

error_log /var/log/nginx/error.log debug;

load_module modules/ngx_http_voms_module.so;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

resolver 127.0.0.11 ipv6=off;

log_format storm '$time_iso8601 [$request_id] $remote_addr - $remote_user "$request" <$upstream_response_time> '
'$ssl_protocol/$ssl_cipher '
'"$ssl_client_s_dn" '
'[$voms_fqans] '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log storm;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

include /etc/nginx/conf.d/*.conf;
}
45 changes: 45 additions & 0 deletions compose-nginx/assets/nginx/storm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
server {
location /internal {
internal;
alias /src/test/resources/storage/nginx;
}
location / {
proxy_pass http://storm-webdav:8086;
proxy_set_header Host $http_host;
proxy_set_header X-VOMS-voms_user $voms_user;
proxy_set_header X-VOMS-ssl_client_ee_s_dn $ssl_client_ee_s_dn;
proxy_set_header X-VOMS-voms_user_ca $voms_user_ca;
proxy_set_header X-VOMS-ssl_client_ee_i_dn $ssl_client_ee_i_dn;
proxy_set_header X-VOMS-voms_fqans $voms_fqans;
proxy_set_header X-VOMS-voms_server $voms_server;
proxy_set_header X-VOMS-voms_server_ca $voms_server_ca;
proxy_set_header X-VOMS-voms_vo $voms_vo;
proxy_set_header X-VOMS-voms_server_uri $voms_server_uri;
proxy_set_header X-VOMS-voms_not_before $voms_not_before;
proxy_set_header X-VOMS-voms_not_after $voms_not_after;
proxy_set_header X-VOMS-voms_generic_attributes $voms_generic_attributes;
proxy_set_header X-VOMS-voms_serial $voms_serial;
proxy_redirect off;
}
listen [::]:8443 ssl http2;
listen 8443 ssl http2;
ssl_certificate /etc/grid-security/hostcert.pem;
ssl_certificate_key /etc/grid-security/hostkey.pem;
ssl_client_certificate /etc/pki/ca-trust/extracted/pem/tls-ca-bundle-all.pem;
ssl_verify_client optional;
ssl_verify_depth 10;
error_page 497 https://$host:8443$request_uri; # https://ma.ttias.be/force-redirect-http-https-custom-port-nginx/#forcing-https-redirects-on-non-standard-ports
}
server {
location /internal {
internal;
alias /src/test/resources/storage/nginx;
}
location / {
proxy_pass http://127.0.0.1:8086;
proxy_set_header Host $http_host;
proxy_redirect off;
}
listen [::]:8085;
listen 8085;
}
2 changes: 2 additions & 0 deletions compose-nginx/assets/wlcg/wlcg-voms.cloud.cnaf.infn.it.lsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/DC=org/DC=terena/DC=tcs/C=IT/ST=Roma/O=Istituto Nazionale di Fisica Nucleare/CN=wlcg-voms.cloud.cnaf.infn.it
/C=NL/O=GEANT Vereniging/CN=GEANT eScience SSL CA 4
31 changes: 31 additions & 0 deletions compose-nginx/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
services:
trust:
image: indigoiam/egi-trustanchors:igi-test-ca
volumes:
- trustanchors:/etc/grid-security/certificates
- cabundle:/etc/pki
environment:
- FORCE_TRUST_ANCHORS_UPDATE=1
nginx-httpg-voms:
image: cnafsd/nginx-httpg-voms
volumes:
- /etc/grid-security/hostcert.pem:/etc/grid-security/hostcert.pem:ro
- /etc/grid-security/hostkey.pem:/etc/grid-security/hostkey.pem:ro
- trustanchors:/etc/grid-security/certificates
- cabundle:/etc/pki
- ../src:/src:z
- ./assets/nginx/nginx.conf:/etc/nginx/nginx.conf:z
- ./assets/nginx/storm.conf:/etc/nginx/conf.d/storm.conf:z
- ./assets/wlcg:/etc/grid-security/vomsdir/wlcg:z
ports:
- "8443:8443"
# to wait the trust service to finish
restart: on-failure
storm-webdav:
build:
context: ../
dockerfile: Dockerfile

volumes:
trustanchors:
cabundle:
3 changes: 3 additions & 0 deletions compose-nginx/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
podman-compose up trust
podman-compose up -d
15 changes: 15 additions & 0 deletions nginx.repo
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
1 change: 1 addition & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
podman stop storm-webdav; podman rm storm-webdav; podman run -d -p 8085:8085 -p 8443:8443 -p 8086:8086 --name storm-webdav localhost/storm-webdav:latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.italiangrid.storm.webdav.authz;

import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AuthenticationManager;

public class VOMSNginxFilter extends VOMSAuthenticationFilter {

public VOMSNginxFilter(AuthenticationManager mgr) {
super(mgr);
}

@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
if (request.getHeader("X-VOMS-voms_user") != null) {
return new X500Principal(request.getHeader("X-VOMS-ssl_client_ee_s_dn")).getName();
}
return null;
}

@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return new Object();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,28 @@
*/
package org.italiangrid.storm.webdav.authz;

import java.math.BigInteger;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpServletRequest;

import org.italiangrid.storm.webdav.authz.vomap.VOMapDetailsService;
import org.italiangrid.voms.VOMSAttribute;
import org.italiangrid.voms.VOMSGenericAttribute;
import org.italiangrid.voms.ac.VOMSACValidator;
import org.italiangrid.voms.ac.impl.VOMSAttributesImpl;
import org.italiangrid.voms.ac.impl.VOMSGenericAttributeImpl;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.core.GrantedAuthority;

Expand All @@ -41,12 +50,14 @@ public class VOMSPreAuthDetailsSource
private final AuthorizationPolicyService policyService;
private final VOMSACValidator validator;
private final VOMapDetailsService voMapDetailsService;
private final boolean nginxReverseProxy;

public VOMSPreAuthDetailsSource(VOMSACValidator vomsValidator,
AuthorizationPolicyService policyService, VOMapDetailsService voMapDetailsService) {
AuthorizationPolicyService policyService, VOMapDetailsService voMapDetailsService, boolean nginxReverseProxy) {
this.policyService = policyService;
this.validator = vomsValidator;
this.voMapDetailsService = voMapDetailsService;
this.nginxReverseProxy = nginxReverseProxy;
}

@Override
Expand Down Expand Up @@ -116,6 +127,45 @@ protected Optional<X509SubjectAuthority> getSubjectAuthority(HttpServletRequest
}

protected List<VOMSAttribute> getAttributes(HttpServletRequest request) {
if (nginxReverseProxy) {
VOMSAttributesImpl attrs = new VOMSAttributesImpl();
attrs.setVO(request.getHeader("X-VOMS-voms_vo"));
if (request.getHeader("X-VOMS-voms_user_ca") != null) {
attrs.setIssuer(new X500Principal(request.getHeader("X-VOMS-ssl_client_ee_i_dn"))); // ???
}
attrs.setFQANs(Arrays.asList(request.getHeader("X-VOMS-voms_fqans").split(",")));
attrs.setHost(request.getHeader("X-VOMS-voms_server_uri").split(":")[0]);
attrs.setPort(Integer.parseInt(request.getHeader("X-VOMS-voms_server_uri").split(":")[1]));
if (request.getHeader("X-VOMS-voms_user") != null) {
attrs.setHolder(new X500Principal(request.getHeader("X-VOMS-ssl_client_ee_s_dn"))); // ???
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
try {
attrs.setNotAfter(simpleDateFormat.parse(request.getHeader("X-VOMS-voms_not_after")));
attrs.setNotBefore(simpleDateFormat.parse(request.getHeader("X-VOMS-voms_not_before")));
} catch (ParseException e) {}
//attrs.setSignature();
if (request.getHeader("X-VOMS-voms_generic_attributes") != null) {
List<VOMSGenericAttribute> generic_attrs = Collections.emptyList();
Pattern pattern = Pattern.compile("n=(\\S*) v=(\\S*) q=(\\S*)");
for (String genericAttribute : request.getHeader("X-VOMS-voms_generic_attributes").split(",")) {
Matcher matcher = pattern.matcher(genericAttribute);
if (matcher.find()) {
VOMSGenericAttributeImpl generic_attr = new VOMSGenericAttributeImpl();
generic_attr.setName(matcher.group(1));
generic_attr.setValue(matcher.group(2));
generic_attr.setContext(matcher.group(3));
generic_attrs.add(generic_attr);
}
}
attrs.setGenericAttributes(generic_attrs);
}
//attrs.setTargets();
//attrs.setAACertificates();
//attrs.setVOMSAC();
attrs.setHolderSerialNumber(new BigInteger(request.getHeader("X-VOMS-voms_serial"), 16));
return List.of(attrs);
}

Optional<X509Certificate[]> chain = Utils.getCertificateChainFromRequest(request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,8 @@ public void setTrustStore(VOMSTrustStoreProperties trustStore) {

private ChecksumStrategy checksumStrategy = ChecksumStrategy.EARLY;

private boolean nginxReverseProxy = false;

private BufferProperties buffer;

private RedirectorProperties redirector;
Expand Down Expand Up @@ -850,6 +852,14 @@ public void setChecksumStrategy(ChecksumStrategy checksumStrategy) {
this.checksumStrategy = checksumStrategy;
}

public boolean getNginxReverseProxy() {
return nginxReverseProxy;
}

public void setNginxReverseProxy(boolean nginxReverseProxy) {
this.nginxReverseProxy = nginxReverseProxy;
}


@Override
public boolean useConscrypt() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ public Resource getResource(String pathInContext) {

}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
resourceService.doGet(request, response, pathResolver, serviceConfig);
}

@Override
protected void doHead(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
*/
package org.italiangrid.storm.webdav.server.servlet.resource;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -26,6 +28,9 @@
import org.eclipse.jetty.server.ResourceService;
import org.eclipse.jetty.util.URIUtil;

import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
import org.italiangrid.storm.webdav.server.PathResolver;

public class StormResourceService extends ResourceService {

private String pathInContext(HttpServletRequest request) {
Expand Down Expand Up @@ -73,4 +78,19 @@ public boolean doHead(HttpServletRequest request, HttpServletResponse response)
return true;
}

public boolean doGet(HttpServletRequest request, HttpServletResponse response, PathResolver resolver, ServiceConfigurationProperties serviceConfig)
throws ServletException, IOException {

if (serviceConfig.getNginxReverseProxy()) {
final String pathInContext = pathInContext(request);
String resolvedPath = resolver.resolvePath(pathInContext);
File f = new File(resolvedPath);
if (f.isFile()) {
response.setHeader("X-Accel-Redirect", "/internal" + pathInContext);
return response.isCommitted();
}
}
return super.doGet(request, response);
}

}
Loading

0 comments on commit a64790d

Please sign in to comment.