]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/client/CmsClient.java
FS utils throws IOException
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / client / CmsClient.java
1 package org.argeo.cms.client;
2
3 import java.io.BufferedInputStream;
4 import java.io.IOException;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.net.URL;
8 import java.net.http.HttpClient;
9 import java.net.http.HttpRequest;
10 import java.net.http.HttpResponse;
11 import java.net.http.HttpResponse.BodyHandler;
12 import java.net.http.HttpResponse.BodyHandlers;
13 import java.net.http.WebSocket;
14 import java.nio.file.Files;
15 import java.nio.file.Path;
16 import java.nio.file.Paths;
17 import java.security.KeyManagementException;
18 import java.security.NoSuchAlgorithmException;
19 import java.security.cert.CertificateException;
20 import java.security.cert.CertificateFactory;
21 import java.security.cert.X509Certificate;
22 import java.util.Collection;
23 import java.util.concurrent.CompletableFuture;
24
25 import javax.net.ssl.SSLContext;
26 import javax.net.ssl.TrustManager;
27 import javax.net.ssl.X509TrustManager;
28 import javax.security.auth.login.LoginContext;
29 import javax.security.auth.login.LoginException;
30
31 import org.argeo.cms.auth.ConsoleCallbackHandler;
32 import org.argeo.cms.auth.RemoteAuthUtils;
33 import org.argeo.cms.http.HttpHeader;
34
35 /** Utility to connect to a remote CMS node. */
36 public class CmsClient {
37 public final static String CLIENT_LOGIN_CONTEXT = "CLIENT";
38
39 private URI uri;
40
41 private HttpClient httpClient;
42 private String gssToken;
43
44 public CmsClient(URI uri) {
45 this.uri = uri;
46 }
47
48 public void login() {
49 String server = uri.getHost();
50
51 URL jaasUrl = CmsClient.class.getResource("jaas-client-ipa.cfg");
52 System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
53 try {
54 LoginContext lc = new LoginContext(CLIENT_LOGIN_CONTEXT, new ConsoleCallbackHandler());
55 lc.login();
56 gssToken = RemoteAuthUtils.createGssToken(lc.getSubject(), "HTTP", server);
57 } catch (LoginException e) {
58 // TODO Auto-generated catch block
59 e.printStackTrace();
60 } finally {
61
62 }
63 }
64
65 public String getAsString() {
66 return getAsString(uri);
67 }
68
69 public String getAsString(URI uri) {
70 uri = normalizeUri(uri);
71 try {
72 HttpClient httpClient = getHttpClient();
73
74 HttpRequest request = HttpRequest.newBuilder().uri(uri) //
75 .header(HttpHeader.AUTHORIZATION.getHeaderName(), HttpHeader.NEGOTIATE + " " + getGssToken()) //
76 .build();
77 BodyHandler<String> bodyHandler = BodyHandlers.ofString();
78 HttpResponse<String> response = httpClient.send(request, bodyHandler);
79 return response.body();
80 // int responseCode = response.statusCode();
81 // System.exit(responseCode);
82 } catch (IOException | InterruptedException e) {
83 throw new RuntimeException("Cannot read " + uri + " as a string", e);
84 }
85 }
86
87 protected URI normalizeUri(URI uri) {
88 if (uri.getHost() != null)
89 return uri;
90 try {
91 String path = uri.getPath();
92 if (path.startsWith("/")) {// absolute
93 return new URI(this.uri.getScheme(), this.uri.getUserInfo(), this.uri.getHost(), this.uri.getPort(),
94 path, uri.getQuery(), uri.getFragment());
95 } else {
96 String thisUriStr = this.uri.toString();
97 if (!thisUriStr.endsWith("/"))
98 thisUriStr = thisUriStr + "/";
99 return URI.create(thisUriStr + path);
100 }
101 } catch (URISyntaxException e) {
102 throw new IllegalArgumentException("Cannot interpret " + uri, e);
103 }
104 }
105
106 public URI getUri() {
107 return uri;
108 }
109
110 String getGssToken() {
111 return gssToken;
112 }
113
114 public HttpClient getHttpClient() {
115 if (httpClient == null) {
116 login();
117 HttpClient client = HttpClient.newBuilder() //
118 .sslContext(ipaSslContext()) //
119 .version(HttpClient.Version.HTTP_1_1) //
120 .build();
121 httpClient = client;
122 }
123 return httpClient;
124 }
125
126 public CompletableFuture<WebSocket> newWebSocket(WebSocket.Listener listener) {
127 return newWebSocket(uri, listener);
128 }
129
130 public CompletableFuture<WebSocket> newWebSocket(URI uri, WebSocket.Listener listener) {
131 CompletableFuture<WebSocket> ws = getHttpClient().newWebSocketBuilder()
132 .header(HttpHeader.AUTHORIZATION.getHeaderName(), HttpHeader.NEGOTIATE + " " + getGssToken())
133 .buildAsync(uri, listener);
134 return ws;
135 }
136
137 @SuppressWarnings("unchecked")
138 protected SSLContext ipaSslContext() {
139 try {
140 final Collection<X509Certificate> certificates;
141 Path caCertificatePath = Paths.get("/etc/ipa/ca.crt");
142 if (Files.exists(caCertificatePath)) {
143 CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
144 try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(caCertificatePath))) {
145 certificates = (Collection<X509Certificate>) certificateFactory.generateCertificates(in);
146 }
147 } else {
148 certificates = null;
149 }
150 TrustManager[] noopTrustManager = new TrustManager[] { new X509TrustManager() {
151 public void checkClientTrusted(X509Certificate[] xcs, String string) {
152 }
153
154 public void checkServerTrusted(X509Certificate[] xcs, String string) {
155 }
156
157 public X509Certificate[] getAcceptedIssuers() {
158 if (certificates == null)
159 return null;
160 return certificates.toArray(new X509Certificate[certificates.size()]);
161 }
162 } };
163
164 SSLContext sc = SSLContext.getInstance("ssl");
165 sc.init(null, noopTrustManager, null);
166 return sc;
167 } catch (KeyManagementException | NoSuchAlgorithmException | CertificateException | IOException e) {
168 throw new IllegalStateException("Cannot create SSL context ", e);
169 }
170 }
171
172 }