9
9
import oracle .jdbc .provider .parameter .ParameterSet ;
10
10
import oracle .sql .json .OracleJsonFactory ;
11
11
import oracle .sql .json .OracleJsonObject ;
12
+ import oracle .sql .json .OracleJsonValue ;
12
13
13
14
import java .io .ByteArrayInputStream ;
14
15
import java .io .ByteArrayOutputStream ;
15
16
import java .io .IOException ;
16
17
import java .io .InputStream ;
17
18
import java .net .HttpURLConnection ;
18
19
import java .net .URL ;
20
+ import java .util .Optional ;
19
21
20
22
import static java .nio .charset .StandardCharsets .UTF_8 ;
21
23
import static oracle .jdbc .provider .parameter .Parameter .CommonAttribute .REQUIRED ;
@@ -29,7 +31,7 @@ public final class HashiVaultSecretsManagerFactory extends HashiVaultResourceFac
29
31
* The name of the key if the secret is a JSON with multiple fields.
30
32
* This is optional.
31
33
*/
32
- public static final Parameter <String > KEY_NAME = Parameter .create ();
34
+ public static final Parameter <String > KEY = Parameter .create ();
33
35
34
36
/**
35
37
* (Optional) The Vault address. If not specified, fallback to system property or environment var.
@@ -45,6 +47,10 @@ public final class HashiVaultSecretsManagerFactory extends HashiVaultResourceFac
45
47
46
48
private static final OracleJsonFactory JSON_FACTORY = new OracleJsonFactory ();
47
49
50
+ private static final String ERROR_VAULT_ADDR = "Vault address not found in parameters, system properties, or environment variables" ;
51
+ private static final String ERROR_VAULT_TOKEN = "Vault token not found in parameters, system properties, or environment variables" ;
52
+
53
+
48
54
/**
49
55
* The single instance of this factory, cached for performance.
50
56
*/
@@ -60,35 +66,30 @@ public static ResourceFactory<String> getInstance() {
60
66
@ Override
61
67
public Resource <String > request (HashiCredentials credentials , ParameterSet parameterSet ) {
62
68
String secretPath = parameterSet .getRequired (SECRET_PATH );
63
- String key = parameterSet .getOptional (KEY_NAME );
64
- String vaultAddrParam = parameterSet .getOptional (VAULT_ADDR );
65
- String vaultTokenParam = parameterSet .getOptional (VAULT_TOKEN );
69
+ // Get required parameters with fallback
70
+ String vaultAddr = getRequiredOrFallback (parameterSet , VAULT_ADDR , "VAULT_ADDR" );
71
+ String vaultToken = getRequiredOrFallback (parameterSet , VAULT_TOKEN , "VAULT_TOKEN" );
72
+ String key = parameterSet .getOptional (KEY );
66
73
67
- String vaultAddr = (vaultAddrParam != null )
68
- ? vaultAddrParam
69
- : System .getProperty ("VAULT_ADDR" , System .getenv ("VAULT_ADDR" ));
74
+ System .out .println ("secretPath: " + secretPath + ", vaultAddr: " + vaultAddr + ", vaultToken: " + vaultToken + ", key: " + key );
70
75
71
- String vaultToken = (vaultTokenParam != null )
72
- ? vaultTokenParam
73
- : System .getProperty ("VAULT_TOKEN" , System .getenv ("VAULT_TOKEN" ));
74
76
75
77
if (vaultAddr == null || vaultAddr .isEmpty ()) {
76
- throw new IllegalStateException (
77
- "Vault address not found in URL parameters, system properties, or environment variables" );
78
+ throw new IllegalStateException (ERROR_VAULT_ADDR );
78
79
}
79
80
if (vaultToken == null || vaultToken .isEmpty ()) {
80
- throw new IllegalStateException (
81
- "Vault token not found in URL parameters, system properties, or environment variables" );
81
+ throw new IllegalStateException (ERROR_VAULT_TOKEN );
82
82
}
83
83
84
+
84
85
String vaultUrl = vaultAddr + secretPath ;
85
86
86
87
// Make the REST call
87
88
String secretString = fetchSecretFromVault (vaultUrl , vaultToken );
88
89
89
90
/*
90
- * If KEY_NAME is specified, we only want a single field from the nested JSON.
91
- * If KEY_NAME is not specified, we return the entire
91
+ * If KEY is specified, we only want a single field from the nested JSON.
92
+ * If KEY is not specified, we return the entire
92
93
* {
93
94
* "data": { ...all fields... }
94
95
* }
@@ -100,28 +101,28 @@ public Resource<String> request(HashiCredentials credentials, ParameterSet param
100
101
}
101
102
102
103
private static String fetchSecretFromVault (String vaultUrl , String token ) {
103
- HttpURLConnection conn = null ;
104
104
try {
105
105
URL url = new URL (vaultUrl );
106
- conn = (HttpURLConnection ) url .openConnection ();
106
+ HttpURLConnection conn = (HttpURLConnection ) url .openConnection ();
107
107
conn .setRequestMethod ("GET" );
108
108
conn .setRequestProperty ("X-Vault-Token" , token );
109
109
conn .setRequestProperty ("Accept" , "application/json" );
110
110
111
- if (conn .getResponseCode () != 200 ) {
111
+ if (conn .getResponseCode () != HttpURLConnection . HTTP_OK ) {
112
112
throw new IllegalStateException (
113
113
"Failed to fetch secret. HTTP error code: " + conn .getResponseCode ());
114
114
}
115
+
116
+ // Use try-with-resources for the InputStream
115
117
try (InputStream in = conn .getInputStream ()) {
116
118
return readStream (in );
119
+ } finally {
120
+ // Explicitly disconnect the connection
121
+ conn .disconnect ();
117
122
}
118
123
} catch (IOException e ) {
119
124
throw new IllegalArgumentException (
120
125
"Failed to read secret from Vault at " + vaultUrl , e );
121
- } finally {
122
- if (conn != null ) {
123
- conn .disconnect ();
124
- }
125
126
}
126
127
}
127
128
@@ -135,6 +136,7 @@ private static String readStream(InputStream in) throws IOException {
135
136
return new String (baos .toByteArray (), UTF_8 );
136
137
}
137
138
139
+
138
140
/**
139
141
* If {@code key} is non-null, parse the JSON from Vault and return only that key's value.
140
142
* Otherwise, return just the nested JSON:
@@ -149,61 +151,43 @@ private static String readStream(InputStream in) throws IOException {
149
151
* }
150
152
*/
151
153
private static String extractValueFromJson (String secretJson , String key , String secretPath ) {
152
- InputStream is = null ;
153
- try {
154
- is = new ByteArrayInputStream (secretJson .getBytes (UTF_8 ));
154
+ try (InputStream is = new ByteArrayInputStream (secretJson .getBytes (UTF_8 ))) {
155
155
OracleJsonObject rootObject = JSON_FACTORY .createJsonTextValue (is ).asJsonObject ();
156
+ OracleJsonObject dataNode = rootObject .getObject ("data" );
157
+ OracleJsonObject nestedData = dataNode .getObject ("data" );
156
158
157
- // Navigate to the second-level "data" object: rootObject.data.data
158
- // Example root:
159
- // {
160
- // "request_id": "...",
161
- // "data": {
162
- // "data": {
163
- // "connect_descriptor": "...",
164
- // "jdbc": {...},
165
- // "password": {...},
166
- // "user": "ADMIN"
167
- // },
168
- // "metadata": {...}
169
- // },
170
- // ...
171
- // }
172
-
173
- OracleJsonObject dataNode = rootObject .getObject ("data" ); // top-level "data"
174
-
175
- OracleJsonObject dataData = dataNode .getObject ("data" ); // nested "data"
176
-
177
-
178
- if (key != null ) {
179
- // Return only that key's value
180
- if (!dataData .containsKey (key )) {
181
- throw new IllegalArgumentException (
182
- "Failed to find key " + key + " in secret: " + secretPath );
183
- }
184
- return dataData .getString (key );
185
-
186
- } else {
187
- // Return just the nested data as:
188
- // {
189
- // "data": {
190
- // "connect_descriptor": "...",
191
- // "jdbc": {...},
192
- // "password": {...},
193
- // "user": "ADMIN"
194
- // }
195
- // }
196
-
197
- return dataData .toString ();
159
+ if (key == null ) {
160
+ return nestedData .toString ();
198
161
}
199
- } finally {
200
- if (is != null ) {
201
- try {
202
- is .close ();
203
- } catch (IOException ignore ) {
204
- // ignore
205
- }
162
+
163
+ OracleJsonValue value = nestedData .get (key );
164
+ if (value == null ) {
165
+ throw new IllegalArgumentException (
166
+ "Key \" " + key + "\" not found in secret at path: " + secretPath );
206
167
}
168
+
169
+ return value .toString ();
170
+ } catch (IOException e ) {
171
+ throw new IllegalArgumentException (
172
+ "Failed to parse JSON for secret at path: " + secretPath , e );
207
173
}
208
174
}
175
+
176
+ private static String getEnvOrProperty (String key ) {
177
+ return System .getProperty (key , System .getenv (key ));
178
+ }
179
+
180
+ private static String getRequiredOrFallback (ParameterSet parameterSet , Parameter <String > parameter , String envKey ) {
181
+ // Try to get the required parameter value
182
+ String value = parameterSet .getOptional (parameter );
183
+ if (value != null ) {
184
+ return value ;
185
+ }
186
+
187
+ // Fallback to environment variables or system properties
188
+ return getEnvOrProperty (envKey );
189
+ }
190
+
191
+
192
+
209
193
}
0 commit comments