View Javadoc
1   package org.apache.maven.it;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.it.util.ResourceExtractor;
23  
24  import java.io.File;
25  import java.io.IOException;
26  import java.io.PrintWriter;
27  import java.util.List;
28  import java.util.Properties;
29  
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.eclipse.jetty.server.HttpConfiguration;
34  import org.eclipse.jetty.server.HttpConnectionFactory;
35  import org.eclipse.jetty.server.NetworkConnector;
36  import org.eclipse.jetty.server.Request;
37  import org.eclipse.jetty.server.SecureRequestCustomizer;
38  import org.eclipse.jetty.server.Server;
39  import org.eclipse.jetty.server.ServerConnector;
40  import org.eclipse.jetty.server.SslConnectionFactory;
41  import org.eclipse.jetty.server.handler.AbstractHandler;
42  import org.eclipse.jetty.util.ssl.SslContextFactory;
43  
44  import static org.eclipse.jetty.http.HttpVersion.HTTP_1_1;
45  
46  /**
47   * This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-2305">MNG-2305</a>.
48   *
49   * @author Benjamin Bentmann
50   */
51  public class MavenITmng2305MultipleProxiesTest
52      extends AbstractMavenIntegrationTestCase
53  {
54  
55      public MavenITmng2305MultipleProxiesTest()
56      {
57          super( "[3.0-alpha-3,)" );
58      }
59  
60      /**
61       * Verify that proxies can be setup for multiple protocols, in this case HTTP and HTTPS. As a nice side effect,
62       * this checks HTTPS tunneling over a web proxy.
63       *
64       * @throws Exception in case of failure
65       */
66      public void testit()
67          throws Exception
68      {
69          File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-2305" );
70  
71          Verifier verifier = newVerifier( testDir.getAbsolutePath() );
72  
73          // NOTE: trust store cannot be reliably configured for the current JVM
74          verifier.setForkJvm( true );
75  
76          // keytool -genkey -alias https.mngit -keypass key-passwd -keystore keystore -storepass store-passwd \
77          //   -validity 4096 -dname "cn=https.mngit, ou=None, L=Seattle, ST=Washington, o=ExampleOrg, c=US" -keyalg RSA
78          String storePath = new File( testDir, "keystore" ).getAbsolutePath();
79          String storePwd = "store-passwd";
80          String keyPwd = "key-passwd";
81  
82          Server server = new Server( 0 );
83          addHttpsConnector( server, storePath, storePwd, keyPwd );
84          server.setHandler( new RepoHandler() );
85          server.start();
86          if ( server.isFailed() )
87          {
88              fail( "Couldn't bind the server socket to a free port!" );
89          }
90          int httpPort = ( (NetworkConnector) server.getConnectors()[0] ).getLocalPort();
91          System.out.println( "Bound server socket to HTTP port " + httpPort );
92          int httpsPort = ( (NetworkConnector) server.getConnectors()[1] ).getLocalPort();
93          System.out.println( "Bound server socket to HTTPS port " + httpsPort );
94  
95          TunnelingProxyServer proxy = new TunnelingProxyServer( 0, "localhost", httpsPort, "https.mngit:443" );
96          proxy.start();
97          int proxyPort = proxy.getPort();
98          System.out.println( "Bound server socket to the proxy port " + proxyPort );
99  
100         try
101         {
102             verifier.setAutoclean( false );
103             verifier.deleteDirectory( "target" );
104             verifier.deleteArtifacts( "org.apache.maven.its.mng2305" );
105             Properties filterProps = verifier.newDefaultFilterProperties();
106             filterProps.setProperty( "@proxy.http@", Integer.toString( httpPort ) );
107             filterProps.setProperty( "@proxy.https@", Integer.toString( proxyPort ) );
108             verifier.filterFile( "settings-template.xml", "settings.xml", "UTF-8", filterProps );
109             verifier.addCliOption( "--settings" );
110             verifier.addCliOption( "settings.xml" );
111             verifier.setSystemProperty( "javax.net.ssl.trustStore", storePath );
112             verifier.setSystemProperty( "javax.net.ssl.trustStorePassword", storePwd );
113             // disable concurrent downloading as not all wagons (e.g. wagon-lightweight-http) are thread-safe regarding proxy settings
114             verifier.setSystemProperty( "maven.artifact.threads", "1" );
115             verifier.executeGoal( "validate" );
116             verifier.verifyErrorFreeLog();
117             verifier.resetStreams();
118         }
119         finally
120         {
121             proxy.stop();
122             server.stop();
123             server.join();
124         }
125 
126         List<String> cp = verifier.loadLines( "target/classpath.txt", "UTF-8" );
127         assertTrue( cp.toString(), cp.contains( "http-0.1.jar" ) );
128         assertTrue( cp.toString(), cp.contains( "https-0.1.jar" ) );
129     }
130 
131     private void addHttpsConnector( Server server, String keyStorePath, String keyStorePassword, String keyPassword )
132     {
133         SslContextFactory sslContextFactory = new SslContextFactory( keyStorePath );
134         sslContextFactory.setKeyStorePassword( keyStorePassword );
135         sslContextFactory.setKeyManagerPassword( keyPassword );
136         HttpConfiguration httpConfiguration = new HttpConfiguration();
137         httpConfiguration.setSecureScheme( "https" );
138         HttpConfiguration httpsConfiguration = new HttpConfiguration( httpConfiguration );
139         httpsConfiguration.addCustomizer( new SecureRequestCustomizer() );
140         ServerConnector httpsConnector = new ServerConnector( server,
141                 new SslConnectionFactory( sslContextFactory, HTTP_1_1.asString() ),
142                 new HttpConnectionFactory( httpsConfiguration ) );
143         server.addConnector( httpsConnector );
144     }
145 
146     static class RepoHandler extends AbstractHandler
147     {
148         public void handle( String target, Request baseRequest, HttpServletRequest request,
149                             HttpServletResponse response )
150             throws IOException
151         {
152             PrintWriter writer = response.getWriter();
153 
154             String uri = request.getRequestURI();
155 
156             if ( !uri.startsWith( "/repo/org/apache/maven/its/mng2305/" + request.getScheme() + "/" ) )
157             {
158                 // HTTP connector serves only http-0.1.jar and HTTPS connector serves only https-0.1.jar
159                 response.setStatus( HttpServletResponse.SC_NOT_FOUND );
160             }
161             else if ( uri.endsWith( ".pom" ) )
162             {
163                 writer.println( "<project>" );
164                 writer.println( "  <modelVersion>4.0.0</modelVersion>" );
165                 writer.println( "  <groupId>org.apache.maven.its.mng2305</groupId>" );
166                 writer.println( "  <artifactId>" + request.getScheme() + "</artifactId>" );
167                 writer.println( "  <version>0.1</version>" );
168                 writer.println( "</project>" );
169                 response.setStatus( HttpServletResponse.SC_OK );
170             }
171             else if ( uri.endsWith( ".jar" ) )
172             {
173                 writer.println( "empty" );
174                 response.setStatus( HttpServletResponse.SC_OK );
175             }
176             else
177             {
178                 response.setStatus( HttpServletResponse.SC_NOT_FOUND );
179             }
180 
181             ( (Request) request ).setHandled( true );
182         }
183     }
184 }