1
1
package no .digipost .signature .client .core .internal .security ;
2
2
3
- import no .digipost .signature .client .Certificates ;
4
3
import no .digipost .signature .client .core .exceptions .ConfigurationException ;
5
4
6
5
import javax .net .ssl .SSLContext ;
7
6
import javax .net .ssl .TrustManagerFactory ;
8
7
9
- import java .io .File ;
10
- import java .io .FileInputStream ;
11
8
import java .io .IOException ;
12
9
import java .io .InputStream ;
13
10
import java .net .URL ;
11
+ import java .nio .file .Files ;
12
+ import java .nio .file .Path ;
13
+ import java .nio .file .Paths ;
14
+ import java .security .GeneralSecurityException ;
14
15
import java .security .KeyManagementException ;
15
16
import java .security .KeyStore ;
16
17
import java .security .KeyStoreException ;
17
18
import java .security .NoSuchAlgorithmException ;
18
19
import java .security .cert .CertificateException ;
19
20
import java .security .cert .CertificateFactory ;
20
21
import java .security .cert .X509Certificate ;
22
+ import java .util .UUID ;
23
+ import java .util .stream .Stream ;
24
+
25
+ import static java .nio .file .Files .isDirectory ;
26
+ import static java .util .stream .Collectors .joining ;
27
+ import static java .util .stream .StreamSupport .stream ;
21
28
22
29
public class TrustStoreLoader {
23
30
@@ -31,93 +38,103 @@ public static KeyStore build(ProvidesCertificateResourcePaths hasCertificatePath
31
38
}
32
39
33
40
return trustStore ;
34
- } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | KeyManagementException e ) {
41
+ } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e ) {
35
42
throw new ConfigurationException ("Unable to load certificates into truststore" , e );
36
43
}
37
44
}
38
45
39
- private static void loadCertificatesInto (String certificateFolder , final KeyStore trustStore ) throws IOException , CertificateException , KeyStoreException , NoSuchAlgorithmException , KeyManagementException {
46
+ private static void loadCertificatesInto (String certificateLocation , KeyStore trustStore ) {
40
47
ResourceLoader certificateLoader ;
41
- if (certificateFolder . indexOf ( "classpath:" ) == 0 ) {
42
- certificateLoader = new ClassPathFileLoader ( certificateFolder );
48
+ if (certificateLocation . startsWith ( ClassPathResourceLoader . CLASSPATH_PATH_PREFIX ) ) {
49
+ certificateLoader = new ClassPathResourceLoader ( certificateLocation );
43
50
} else {
44
- certificateLoader = new FileLoader (certificateFolder );
51
+ certificateLoader = new FileLoader (certificateLocation );
45
52
}
46
53
47
- certificateLoader .forEachFile (new ForFile () {
48
- @ Override
49
- void call (String fileName , InputStream contents ) {
50
- try {
51
- X509Certificate ca = (X509Certificate ) CertificateFactory .getInstance ("X.509" ).generateCertificate (contents );
52
- trustStore .setCertificateEntry (fileName , ca );
53
- } catch (CertificateException | KeyStoreException e ) {
54
- throw new ConfigurationException ("Unable to load certificate in " + fileName );
55
- }
56
- }
54
+ certificateLoader .forEachFile ((fileName , contents ) -> {
55
+ X509Certificate ca = (X509Certificate ) CertificateFactory .getInstance ("X.509" ).generateCertificate (contents );
56
+ trustStore .setCertificateEntry (fileName , ca );
57
57
});
58
58
59
+ try {
60
+ TrustManagerFactory tmf = TrustManagerFactory .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
61
+ tmf .init (trustStore );
59
62
60
- TrustManagerFactory tmf = TrustManagerFactory .getInstance (TrustManagerFactory . getDefaultAlgorithm () );
61
- tmf .init (trustStore );
62
-
63
- SSLContext context = SSLContext . getInstance ( "TLS" );
64
- context . init ( null , tmf . getTrustManagers (), null );
63
+ SSLContext context = SSLContext .getInstance ("TLS" );
64
+ context .init (null , tmf . getTrustManagers (), null );
65
+ } catch ( NoSuchAlgorithmException | KeyStoreException | KeyManagementException e ) {
66
+ throw new ConfigurationException ( "Error initializing SSLContext for certification location " + certificateLocation , e );
67
+ }
65
68
}
66
69
67
- private static class ClassPathFileLoader implements ResourceLoader {
70
+
71
+ private static class ClassPathResourceLoader implements ResourceLoader {
68
72
69
73
static final String CLASSPATH_PATH_PREFIX = "classpath:" ;
70
74
71
- private final String certificatePath ;
75
+ private final String resourceName ;
72
76
73
- ClassPathFileLoader (String certificateFolder ) {
74
- this .certificatePath = certificateFolder . substring (CLASSPATH_PATH_PREFIX . length () );
77
+ ClassPathResourceLoader (String resourceName ) {
78
+ this .resourceName = resourceName . replaceFirst (CLASSPATH_PATH_PREFIX , "" );
75
79
}
76
80
77
81
@ Override
78
- public void forEachFile (ForFile forEachFile ) throws IOException {
79
- URL contentsUrl = Certificates .class .getResource (certificatePath );
80
- if (contentsUrl == null ) {
81
- throw new ConfigurationException (certificatePath + " was not found" );
82
+ public void forEachFile (ForFile forEachFile ) {
83
+ URL resourceUrl = TrustStoreLoader .class .getResource (resourceName );
84
+ if (resourceUrl == null ) {
85
+ throw new ConfigurationException (resourceName + " not found on classpath " );
82
86
}
83
- try (InputStream inputStream = contentsUrl .openStream ()){
84
- forEachFile .call (new File (contentsUrl .getFile ()).getName (), inputStream );
87
+
88
+ try (InputStream inputStream = resourceUrl .openStream ()) {
89
+ forEachFile .call (generateAlias (Paths .get (resourceUrl .getPath ())), inputStream );
90
+ } catch (Exception e ) {
91
+ throw new ConfigurationException ("Unable to load certificate from classpath: " + resourceName , e );
85
92
}
86
93
}
87
94
}
88
95
89
96
private static class FileLoader implements ResourceLoader {
90
- private final File path ;
97
+ private final Path path ;
91
98
92
99
FileLoader (String certificateFolder ) {
93
- this .path = new File (certificateFolder );
100
+ this .path = Paths . get (certificateFolder );
94
101
}
95
102
96
103
@ Override
97
- public void forEachFile (ForFile forEachFile ) throws IOException {
98
- if (!this . path . isDirectory ()) {
104
+ public void forEachFile (ForFile forEachFile ) {
105
+ if (!isDirectory (path )) {
99
106
throw new ConfigurationException ("Certificate path '" + this .path + "' is not a directory. " +
100
107
"It should point to a directory containing certificates." );
101
108
}
102
- File [] files = this .path .listFiles ();
103
- if (files == null ) {
104
- throw new ConfigurationException ("Unable to read certificates from '" + path + "'. Make sure it's the correct path." );
105
- }
106
109
107
- for (File file : files ) {
108
- try (InputStream contents = new FileInputStream (file )) {
109
- forEachFile .call (file .getName (), contents );
110
- }
110
+ try (Stream <Path > files = Files .list (path )) {
111
+ files .forEach (file -> {
112
+ try (InputStream contents = Files .newInputStream (file )) {
113
+ forEachFile .call (generateAlias (file ), contents );
114
+ } catch (Exception e ) {
115
+ throw new ConfigurationException ("Unable to load certificate from file " + file , e );
116
+ }
117
+ });
118
+ } catch (IOException e ) {
119
+ throw new ConfigurationException ("Error reading certificates from " + path , e );
111
120
}
112
121
}
113
122
}
114
123
115
124
private interface ResourceLoader {
116
- void forEachFile (ForFile forEachFile ) throws IOException ;
125
+ void forEachFile (ForFile forEachFile );
126
+ }
127
+
128
+ @ FunctionalInterface
129
+ private interface ForFile {
130
+ void call (String fileName , InputStream contents ) throws IOException , GeneralSecurityException ;
117
131
}
118
132
119
- private abstract static class ForFile {
120
- abstract void call (String fileName , InputStream contents );
133
+ private static String generateAlias (Path location ) {
134
+ return stream (location .normalize ().spliterator (), false )
135
+ .reduce ((e1 , e2 ) -> e1 .getFileName ().resolve (e2 ))
136
+ .map (nameBase -> stream (nameBase .spliterator (), false ).map (Path ::toString ).collect (joining (":" )))
137
+ .orElseGet (() -> UUID .randomUUID ().toString ());
121
138
}
122
139
123
140
}
0 commit comments