diff --git a/collector/extensions/resync/index.js b/collector/extensions/resync/index.js index 3ca1f44ab6e..423d050a18e 100644 --- a/collector/extensions/resync/index.js +++ b/collector/extensions/resync/index.js @@ -62,6 +62,8 @@ async function resyncConfluence({ chunkSource }, response) { spaceKey: source.searchParams.get('spaceKey'), accessToken: source.searchParams.get('token'), username: source.searchParams.get('username'), + cloud: source.searchParams.get('cloud') === 'true', + bypassSSL: source.searchParams.get('bypassSSL') === 'true', }); if (!success) throw new Error(`Failed to sync Confluence page content. ${reason}`); diff --git a/collector/utils/extensions/Confluence/ConfluenceLoader/index.js b/collector/utils/extensions/Confluence/ConfluenceLoader/index.js index d84a64fbeab..41c1e94d065 100644 --- a/collector/utils/extensions/Confluence/ConfluenceLoader/index.js +++ b/collector/utils/extensions/Confluence/ConfluenceLoader/index.js @@ -14,6 +14,7 @@ class ConfluencePagesLoader { expand = "body.storage,version", personalAccessToken, cloud = true, + bypassSSL = false, }) { this.baseUrl = baseUrl; this.spaceKey = spaceKey; @@ -23,6 +24,7 @@ class ConfluencePagesLoader { this.expand = expand; this.personalAccessToken = personalAccessToken; this.cloud = cloud; + this.bypassSSL = bypassSSL; } get authorizationHeader() { @@ -60,9 +62,24 @@ class ConfluencePagesLoader { if (authHeader) { initialHeaders.Authorization = authHeader; } - const response = await fetch(url, { + + // Configure fetch options with SSL bypass if enabled + const fetchOptions = { headers: initialHeaders, - }); + }; + + // If SSL bypass is enabled, set the NODE_TLS_REJECT_UNAUTHORIZED environment variable + if (this.bypassSSL) { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + } + + const response = await fetch(url, fetchOptions); + + // Reset the environment variable after the request + if (this.bypassSSL) { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1'; + } + if (!response.ok) { throw new Error( `Failed to fetch ${url} from Confluence: ${response.status}` @@ -70,6 +87,10 @@ class ConfluencePagesLoader { } return await response.json(); } catch (error) { + // Reset the environment variable in case of error + if (this.bypassSSL) { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1'; + } throw new Error(`Failed to fetch ${url} from Confluence: ${error}`); } } diff --git a/collector/utils/extensions/Confluence/index.js b/collector/utils/extensions/Confluence/index.js index 7e31077799e..ee2e8c4eab3 100644 --- a/collector/utils/extensions/Confluence/index.js +++ b/collector/utils/extensions/Confluence/index.js @@ -20,6 +20,7 @@ async function loadConfluence( accessToken = null, cloud = true, personalAccessToken = null, + bypassSSL = false, }, response ) { @@ -54,6 +55,7 @@ async function loadConfluence( accessToken, cloud, personalAccessToken, + bypassSSL, }); const { docs, error } = await loader @@ -100,7 +102,7 @@ async function loadConfluence( description: doc.metadata.title, docSource: `${origin} Confluence`, chunkSource: generateChunkSource( - { doc, baseUrl: origin, spaceKey, accessToken, username, cloud }, + { doc, baseUrl: origin, spaceKey, accessToken, username, cloud, bypassSSL }, response.locals.encryptionWorker ), published: new Date().toLocaleString(), @@ -144,6 +146,7 @@ async function fetchConfluencePage({ username, accessToken, cloud = true, + bypassSSL = false, }) { if (!pageUrl || !baseUrl || !spaceKey || !username || !accessToken) { return { @@ -177,6 +180,7 @@ async function fetchConfluencePage({ username, accessToken, cloud, + bypassSSL, }); const { docs, error } = await loader @@ -240,7 +244,7 @@ function validBaseUrl(baseUrl) { * @returns {string} */ function generateChunkSource( - { doc, baseUrl, spaceKey, accessToken, username, cloud }, + { doc, baseUrl, spaceKey, accessToken, username, cloud, bypassSSL }, encryptionWorker ) { const payload = { @@ -249,6 +253,7 @@ function generateChunkSource( token: accessToken, username, cloud, + bypassSSL, }; return `confluence://${doc.metadata.url}?payload=${encryptionWorker.encrypt( JSON.stringify(payload) diff --git a/frontend/src/components/Modals/ManageWorkspace/DataConnectors/Connectors/Confluence/index.jsx b/frontend/src/components/Modals/ManageWorkspace/DataConnectors/Connectors/Confluence/index.jsx index 3dd9c8e4dd6..cebd0366347 100644 --- a/frontend/src/components/Modals/ManageWorkspace/DataConnectors/Connectors/Confluence/index.jsx +++ b/frontend/src/components/Modals/ManageWorkspace/DataConnectors/Connectors/Confluence/index.jsx @@ -9,6 +9,7 @@ export default function ConfluenceOptions() { const { t } = useTranslation(); const [loading, setLoading] = useState(false); const [accessType, setAccessType] = useState("username"); + const [isCloud, setIsCloud] = useState(true); const handleSubmit = async (e) => { e.preventDefault(); @@ -31,6 +32,7 @@ export default function ConfluenceOptions() { accessToken: form.get("accessToken"), cloud: form.get("isCloud") === "true", personalAccessToken: form.get("personalAccessToken"), + bypassSSL: form.get("bypassSSL") === "true", }); if (!!error) { @@ -77,6 +79,7 @@ export default function ConfluenceOptions() { autoComplete="off" spellCheck={false} defaultValue="true" + onChange={(e) => setIsCloud(e.target.value === "true")} > @@ -198,7 +201,7 @@ export default function ConfluenceOptions() {
{t("connectors.confluence.token_explained_start")}
+ {!isCloud && (
+
+ {t("connectors.confluence.bypass_ssl_explained")}
+