4040import oracle .jdbc .provider .aws .secrets .SecretsManagerFactory ;
4141import oracle .jdbc .provider .parameter .ParameterSet ;
4242import oracle .jdbc .spi .OracleConfigurationSecretProvider ;
43+ import oracle .sql .json .OracleJsonException ;
44+ import oracle .sql .json .OracleJsonFactory ;
4345import oracle .sql .json .OracleJsonObject ;
4446
47+ import java .io .ByteArrayInputStream ;
48+ import java .nio .charset .StandardCharsets ;
4549import java .util .Base64 ;
4650import java .util .Map ;
4751
52+ import static oracle .jdbc .provider .aws .configuration .AwsConfigurationParameters .FIELD_NAME ;
4853import static oracle .jdbc .provider .aws .configuration .AwsSecretsManagerConfigurationProvider .PARAMETER_SET_PARSER ;
4954
5055public class AwsJsonSecretsManagerProvider
5156 implements OracleConfigurationSecretProvider {
57+
58+ private static final OracleJsonFactory JSON_FACTORY = new OracleJsonFactory ();
59+
5260 /**
5361 * {@inheritDoc}
5462 * <p>
@@ -62,24 +70,59 @@ public class AwsJsonSecretsManagerProvider
6270 * <pre>{@code
6371 * "password": {
6472 * "type": "awssecretsmanager",
65- * "value": "<secret-name>"
73+ * "value": "<secret-name>",
74+ * "field_name": "<field-name>"
6675 * }
6776 * }</pre>
6877 *
78+ * <p>
79+ * The {@code field_name} parameter indicates the key whose value should
80+ * be extracted as the secret. When there are multiple key-value pairs
81+ * present, specifying this parameter is mandatory in order to
82+ * unambiguously select the desired secret value. If the secret contains
83+ * only a single entry and no {@code field_name} is provided, that sole
84+ * value will be used. In cases where the secret is plain text,
85+ * the {@code field_name} parameter is not required.
86+ * </p>
87+ *
6988 * @param map Map object to be parsed
7089 * @return encoded char array in base64 format that represents the retrieved
7190 * Secret.
7291 */
7392 @ Override
7493 public char [] getSecret (Map <String , String > map ) {
7594 ParameterSet parameterSet = PARAMETER_SET_PARSER .parseNamedValues (map );
95+ String fieldName = parameterSet .getOptional (FIELD_NAME );
7696
7797 String secretString = SecretsManagerFactory .getInstance ()
7898 .request (parameterSet )
7999 .getContent ();
80100
101+ String extractedSecret ;
102+
103+ try {
104+ OracleJsonObject jsonObject = JSON_FACTORY .createJsonTextValue (
105+ new ByteArrayInputStream (secretString .getBytes (StandardCharsets .UTF_8 )))
106+ .asJsonObject ();
107+
108+ if (fieldName != null ) {
109+ if (!jsonObject .containsKey (fieldName )) {
110+ throw new IllegalStateException ("Field '" + fieldName + "' not found in secret JSON." );
111+ }
112+ extractedSecret = jsonObject .get (fieldName ).asJsonString ().getString ();
113+ } else if (jsonObject .size () == 1 ) {
114+ extractedSecret = jsonObject .values ().iterator ().next ().asJsonString ().getString ();
115+ } else {
116+ throw new IllegalStateException (
117+ "FIELD_NAME is required when multiple keys exist in the secret JSON" );
118+ }
119+
120+ } catch (OracleJsonException e ) {
121+ extractedSecret = secretString ;
122+ }
123+
81124 return Base64 .getEncoder ()
82- .encodeToString (secretString .getBytes ())
125+ .encodeToString (extractedSecret .getBytes (StandardCharsets . UTF_8 ))
83126 .toCharArray ();
84127 }
85128
0 commit comments