001/*
002 * Copyright (c) 2026, Oracle and/or its affiliates.
003 *
004 * Licensed under the Universal Permissive License Version 1.0 as shown at
005 * https://oss.oracle.com/licenses/upl/
006 */
007package com.oracle.database.selectai.model;
008
009/**
010 * Configuration used to create an Oracle {@code DBMS_CLOUD} credential.
011 * <p>
012 * Select AI profiles reference credentials so the database can authenticate to
013 * an AI provider or object storage service. This configuration supports both
014 * username/password credentials and OCI API signing key credentials. Secret
015 * values are passed to the database credential creation call; they are not used
016 * directly by Java after the credential has been created.
017 * <p>
018 * Secret values are retained in memory as {@link String} values so they can be
019 * bound to {@code DBMS_CLOUD.CREATE_CREDENTIAL}. The SDK does not log password
020 * or private-key values. Applications should not log, persist, or expose this
021 * configuration in diagnostics.
022 * <p>
023 * A name-only configuration can be used to reference or drop an existing
024 * credential. Credential creation validates that the configuration contains
025 * either username/password fields or complete OCI signing-key fields, but not
026 * both.
027 *
028 * @see <a href="https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/select-ai-manage-profiles.html">
029 *      Select AI prerequisites and credentials</a>
030 */
031public final class CredentialConfig {
032
033    /** Database credential name passed to {@code DBMS_CLOUD.CREATE_CREDENTIAL}. */
034    private final String credentialName;
035    /** Username used for username/password cloud service credentials. */
036    private final String username;
037    /** Password used for username/password cloud service credentials. */
038    private final String password;
039    /** OCI user OCID used as the credential username. */
040    private final String userOcid;
041    /** OCI tenancy OCID associated with the signing key. */
042    private final String tenancyOcid;
043    /** Private key material used by Oracle Database to sign OCI requests. */
044    private final String privateKey;
045    /** Fingerprint for the public key uploaded to OCI. */
046    private final String fingerprint;
047
048    private CredentialConfig(Builder builder) {
049        this.credentialName = builder.credentialName;
050        this.username = builder.username;
051        this.password = builder.password;
052        this.userOcid = builder.userOcid;
053        this.tenancyOcid = builder.tenancyOcid;
054        this.privateKey = builder.privateKey;
055        this.fingerprint = builder.fingerprint;
056    }
057
058    /**
059     * Creates a builder for a credential with the required database credential name.
060     *
061     * @param credentialName database credential name
062     * @return builder initialized with mandatory credential name
063     * @throws IllegalArgumentException when {@code credentialName} is null or blank
064     */
065    public static Builder builder(String credentialName) {
066        return new Builder(credentialName);
067    }
068
069    /**
070     * Creates a username/password credential configuration.
071     *
072     * @param credentialName database credential name
073     * @param username cloud service username
074     * @param password cloud service password, or {@code null} when the target
075     *                 service does not require one
076     * @return credential configuration for username/password credential creation
077     * @throws IllegalArgumentException when {@code credentialName} is null or blank
078     */
079    public static CredentialConfig usernamePassword(String credentialName,
080                                                    String username,
081                                                    String password) {
082        return builder(credentialName)
083                .username(username)
084                .password(password)
085                .build();
086    }
087
088    /**
089     * Creates an OCI signing-key credential configuration.
090     *
091     * @param credentialName database credential name
092     * @param userOcid OCI user OCID
093     * @param tenancyOcid OCI tenancy OCID
094     * @param privateKey PEM private key material
095     * @param fingerprint OCI API key fingerprint
096     * @return credential configuration for OCI signing-key credential creation
097     * @throws IllegalArgumentException when {@code credentialName} is null or blank
098     */
099    public static CredentialConfig ociSigningKey(String credentialName,
100                                                 String userOcid,
101                                                 String tenancyOcid,
102                                                 String privateKey,
103                                                 String fingerprint) {
104        return builder(credentialName)
105                .userOcid(userOcid)
106                .tenancyOcid(tenancyOcid)
107                .privateKey(privateKey)
108                .fingerprint(fingerprint)
109                .build();
110    }
111
112    /**
113     * Returns the database credential name.
114     *
115     * @return credential name
116     */
117    public String getCredentialName() {
118        return credentialName;
119    }
120
121    /**
122     * Returns the username used for username/password cloud service credentials.
123     *
124     * @return username, or {@code null} when not set
125     */
126    public String getUsername() {
127        return username;
128    }
129
130    /**
131     * Returns the password.
132     * <p>
133     * This value is sensitive. Do not log, persist, or expose it in diagnostics.
134     * The SDK uses it only to bind DBMS_CLOUD.CREATE_CREDENTIAL parameters.
135     *
136     * @return password, or {@code null} when not set.
137     */
138    public String getPassword() {
139        return password;
140    }
141
142    /**
143     * Returns the OCI user OCID stored in the credential.
144     *
145     * @return OCI user OCID, or {@code null} when not set
146     */
147    public String getUserOcid() {
148        return userOcid;
149    }
150
151    /**
152     * Returns the OCI tenancy OCID stored in the credential.
153     *
154     * @return OCI tenancy OCID, or {@code null} when not set
155     */
156    public String getTenancyOcid() {
157        return tenancyOcid;
158    }
159
160    /**
161     * Returns the private key material stored in the credential request.
162     * <p>
163     * This value is sensitive. Do not log, persist, or expose it in diagnostics.
164     * The SDK uses it only to bind DBMS_CLOUD.CREATE_CREDENTIAL parameters.
165     *
166     * @return private key material, or {@code null} when not set
167     */
168    public String getPrivateKey() {
169        return privateKey;
170    }
171
172    /**
173     * Returns the fingerprint for the OCI API signing key.
174     *
175     * @return key fingerprint, or {@code null} when not set
176     */
177    public String getFingerprint() {
178        return fingerprint;
179    }
180
181    /**
182     * Builder for {@link CredentialConfig}.
183     */
184    public static final class Builder {
185
186        /** Required database credential name. */
187        private final String credentialName;
188        /** Optional username for username/password credentials. */
189        private String username;
190        /** Optional password for username/password credentials. */
191        private String password;
192        /** Optional OCI user OCID. */
193        private String userOcid;
194        /** Optional OCI tenancy OCID. */
195        private String tenancyOcid;
196        /** Optional private key material. */
197        private String privateKey;
198        /** Optional key fingerprint. */
199        private String fingerprint;
200
201        private Builder(String credentialName) {
202            if (credentialName == null || credentialName.isBlank()) {
203                throw new IllegalArgumentException("credentialName must not be null or blank");
204            }
205            this.credentialName = credentialName;
206        }
207
208        /**
209         * Sets the username for username/password cloud service credentials.
210         * <p>
211         * A blank username is invalid when this configuration is used to create
212         * a username/password credential.
213         *
214         * @param username cloud service username
215         * @return this builder instance
216         */
217        public Builder username(String username) {
218            this.username = username;
219            return this;
220        }
221
222        /**
223         * Sets the password for username/password cloud service credentials.
224         * <p>
225         * The password is optional for {@code DBMS_CLOUD.CREATE_CREDENTIAL};
226         * when not supplied, the SDK passes {@code null} to the database.
227         * Supplying a password without a username is invalid when this
228         * configuration is used to create a credential.
229         *
230         * @param password cloud service password
231         * @return this builder instance
232         */
233        public Builder password(String password) {
234            this.password = password;
235            return this;
236        }
237
238        /**
239         * Sets the OCI user OCID.
240         * <p>
241         * When this configuration is used to create an OCI signing-key
242         * credential, user OCID, tenancy OCID, private key, and fingerprint must
243         * all be supplied.
244         *
245         * @param userOcid OCI user OCID
246         * @return this builder instance
247         */
248        public Builder userOcid(String userOcid) {
249            this.userOcid = userOcid;
250            return this;
251        }
252
253        /**
254         * Sets the OCI tenancy OCID.
255         * <p>
256         * When this configuration is used to create an OCI signing-key
257         * credential, user OCID, tenancy OCID, private key, and fingerprint must
258         * all be supplied.
259         *
260         * @param tenancyOcid OCI tenancy OCID
261         * @return this builder instance
262         */
263        public Builder tenancyOcid(String tenancyOcid) {
264            this.tenancyOcid = tenancyOcid;
265            return this;
266        }
267
268        /**
269         * Sets the PEM private key material.
270         * <p>
271         * This value is sensitive. Do not log, persist, or expose it in
272         * diagnostics. When this configuration is used to create an OCI
273         * signing-key credential, user OCID, tenancy OCID, private key, and
274         * fingerprint must all be supplied.
275         *
276         * @param privateKey private key material
277         * @return this builder instance
278         */
279        public Builder privateKey(String privateKey) {
280            this.privateKey = privateKey;
281            return this;
282        }
283
284        /**
285         * Sets the OCI public key fingerprint.
286         * <p>
287         * When this configuration is used to create an OCI signing-key
288         * credential, user OCID, tenancy OCID, private key, and fingerprint must
289         * all be supplied.
290         *
291         * @param fingerprint OCI API key fingerprint
292         * @return this builder instance
293         */
294        public Builder fingerprint(String fingerprint) {
295            this.fingerprint = fingerprint;
296            return this;
297        }
298
299        /**
300         * Builds the immutable credential configuration.
301         * <p>
302         * This method validates only the credential name supplied to
303         * {@link #builder(String)}. Complete create-time validation is performed
304         * by {@code Credential.create()} so name-only configurations remain
305         * usable for credential references and drop operations.
306         *
307         * @return immutable CredentialConfig assembled from current builder state
308         */
309        public CredentialConfig build() {
310            return new CredentialConfig(this);
311        }
312    }
313
314}