@docupace/pipeline 1.0.32 → 1.0.33-alpha-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.32",
3
+ "version": "1.0.33-alpha-2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "dependencies": {
18
18
  "@changesets/cli": "^2.27.10",
19
19
  "@docupace/core-client": "^0.1.59",
20
- "auth0-deploy-cli": "^7.24.3",
20
+ "auth0-deploy-cli": "^8.8.0",
21
21
  "axios": "^1.7.9",
22
22
  "commander": "^12.1.0",
23
23
  "dotenv": "^16.4.7",
@@ -1,75 +1,72 @@
1
1
  import axios from 'axios';
2
2
 
3
- import {
4
- createAlias
5
- } from '../next/alias.js';
3
+ import { createAlias } from '../next/alias.js';
6
4
 
7
- import {getAuth0AuthToken} from './configure.js';
5
+ import { getAuth0AuthToken } from './configure.js';
8
6
 
9
- import {
10
- getVaultSecrets,
11
- } from './vault.js';
7
+ import { getVaultSecrets } from './vault.js';
12
8
 
13
- import {
14
- getVaultSecretsConfigs,
15
- } from '../next/config.js';
9
+ import { getVaultSecretsConfigs } from '../next/config.js';
16
10
 
17
- import {
18
- cloneEnvRepository,
19
- readDeployConfig,
20
- } from '../next/deploy.js';
11
+ import { cloneEnvRepository, readDeployConfig } from '../next/deploy.js';
21
12
 
22
- export async function getCCAlias ({application, auth0Domain, auth0AuthToken}){
13
+ export async function getCCAlias({ application, auth0Domain, auth0AuthToken }) {
23
14
  console.log(`Forming alias name for application ${application}...`);
24
15
 
25
16
  try {
26
- const auth0Response = await axios.get(`https://${auth0Domain}/api/v2/clients`, {
27
- headers: {authorization: `Bearer ${auth0AuthToken}`},
28
- });
29
-
30
- const appAuth0ClientIdData = auth0Response.data.find(client => client.name === `${application}`);
17
+ const auth0Response = await axios.get(
18
+ `https://${auth0Domain}/api/v2/clients`,
19
+ {
20
+ headers: { authorization: `Bearer ${auth0AuthToken}` },
21
+ },
22
+ );
23
+
24
+ const appAuth0ClientIdData = auth0Response.data.find(
25
+ (client) => client.name === `${application}`,
26
+ );
31
27
  const appAuth0ClientId = appAuth0ClientIdData.client_id;
32
28
 
33
29
  console.log(`Client Credentials Alias: ${appAuth0ClientId}@clients`);
34
30
  return `${appAuth0ClientId}@clients`;
35
31
  } catch (err) {
36
- console.error(`Failed to form alias name for application: ${application}: ${err.message}`);
32
+ console.error(
33
+ `Failed to form alias name for application: ${application}: ${err.message}`,
34
+ );
37
35
  }
38
36
  }
39
37
 
40
38
  export async function configureAlias(site, env, username, password, realm) {
41
-
42
39
  console.log(`Creating alias for site: ${site} in env: ${env}`);
43
-
44
- const commonSecretsPath = getVaultSecretsConfigs(site).commonSecretsPath;
45
- console.log(`commonSecretsPath => ${commonSecretsPath}`)
46
- const commonSecrets = await getVaultSecrets(commonSecretsPath);
47
-
48
40
  // Site Common Secrets
49
- const siteCommonSecretsPath = getVaultSecretsConfigs(site).siteCommonSecretsPath;
50
- console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`)
41
+ const siteCommonSecretsPath =
42
+ getVaultSecretsConfigs(site).siteCommonSecretsPath;
43
+ console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`);
51
44
  const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
52
45
 
53
- const auth0Domain = `docupace-${env}-${site}.us.auth0.com`
46
+ const auth0Domain = `docupace-${env}-${site}.us.auth0.com`;
54
47
  const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
55
48
  const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
56
- const auth0Token = await getAuth0AuthToken(auth0Domain, auth0ClientId, auth0ClientSecret);
49
+ const auth0Token = await getAuth0AuthToken(
50
+ auth0Domain,
51
+ auth0ClientId,
52
+ auth0ClientSecret,
53
+ );
57
54
 
58
55
  await cloneEnvRepository(env);
59
56
 
60
- const { deployConfig: deployGraphQLServerConfig} = await readDeployConfig('graphql-server', env, site, 'values');
57
+ const { deployConfig: deployGraphQLServerConfig } = await readDeployConfig(
58
+ 'graphql-server',
59
+ env,
60
+ site,
61
+ 'values',
62
+ );
61
63
  const coreUrl = deployGraphQLServerConfig.graphqlServer.coreUrl;
62
64
 
63
65
  const clientCredentialsAlias = await getCCAlias({
64
66
  application: 'docupace-graphql-client-credentials',
65
67
  auth0Domain: auth0Domain,
66
- auth0AuthToken: auth0Token
68
+ auth0AuthToken: auth0Token,
67
69
  });
68
70
 
69
- await createAlias(
70
- coreUrl,
71
- username,
72
- password,
73
- realm,
74
- clientCredentialsAlias);
71
+ await createAlias(coreUrl, username, password, realm, clientCredentialsAlias);
75
72
  }
package/src/auth0/cli.js CHANGED
@@ -1,34 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Command } from 'commander';
4
- import {
5
- configureFromSite
6
- } from './configure.js';
7
- import {
8
- getVaultSecrets
9
- } from './vault.js'
4
+ import { configureFromSite } from './configure.js';
5
+ import { getVaultSecrets } from './vault.js';
10
6
 
11
7
  import dotenv from 'dotenv';
12
- import {
13
- configureAlias
14
- } from "./alias.js";
8
+ import { configureAlias } from './alias.js';
9
+ import { exportConf } from './export.js';
10
+ import { getAuth0Metadata } from './metadata.js';
15
11
 
16
12
  dotenv.config({ path: ['.env.pipeline.local', 'config/.env.pipeline.local'] });
17
13
 
18
14
  const program = new Command();
19
15
 
20
16
  program
21
- .command('configureFromSite <fromSite> <toSite> <fromEnv> <toEnv> <deployUI> <deployGraphQLServer> <useNewDomain> <configureMFA>')
22
- .description('Configure the Auth0 tenants in env for the given site')
23
- .action(async (fromSite, toSite, fromEnv,toEnv, deployUI, deployGraphQLServer, useNewDomain, configureMFA) => {
24
- await configureFromSite(fromSite, toSite, fromEnv, toEnv, deployUI, deployGraphQLServer, useNewDomain, configureMFA);
25
- });
17
+ .command(
18
+ 'configureFromSite <fromSite> <toSite> <fromEnv> <toEnv> <deployUI> <deployGraphQLServer> <useNewDomain>',
19
+ )
20
+ .description('Configure the Auth0 tenants in env for the given site')
21
+ .action(
22
+ async (
23
+ fromSite,
24
+ toSite,
25
+ fromEnv,
26
+ toEnv,
27
+ deployUI,
28
+ deployGraphQLServer,
29
+ useNewDomain,
30
+ ) => {
31
+ await configureFromSite(
32
+ fromSite,
33
+ toSite,
34
+ fromEnv,
35
+ toEnv,
36
+ deployUI,
37
+ deployGraphQLServer,
38
+ useNewDomain,
39
+ );
40
+ },
41
+ );
26
42
 
27
43
  program
28
44
  .command('getVaultSecrets <vaultPath>')
29
45
  .description('Get Secrets for Vault PATH')
30
46
  .action(async (vaultPath) => {
31
- await getVaultSecrets(vaultPath);
47
+ const data = await getVaultSecrets(vaultPath);
48
+ console.log(JSON.stringify(data, 'null', 2));
32
49
  });
33
50
 
34
51
  program
@@ -38,4 +55,18 @@ program
38
55
  await configureAlias(site, env, username, password, realm);
39
56
  });
40
57
 
58
+ program
59
+ .command('exportConf <site> <env>')
60
+ .description('Export Auth0 configuration for the given site')
61
+ .action(async (site, env) => {
62
+ await exportConf(site, env);
63
+ });
64
+
65
+ program
66
+ .command('getAuth0Metadata <site> <env>')
67
+ .description('Get Auth0 metadata for the given site')
68
+ .action(async (site, env) => {
69
+ await getAuth0Metadata(site, env);
70
+ });
71
+
41
72
  program.parse(process.argv);
@@ -2,27 +2,15 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import axios from 'axios';
4
4
  import crypto from 'crypto';
5
- import { deploy } from 'auth0-deploy-cli';
6
- import fl from 'fs/promises';
7
5
 
8
6
  import {
9
7
  cloneEnvRepository,
10
- cloneRepository,
11
8
  readDeployConfig,
12
- pushDeployConfig
9
+ pushDeployConfig,
13
10
  } from '../next/deploy.js';
14
11
 
15
- import {
16
- getVaultSecrets,
17
- updateVaultSecrets
18
- } from './vault.js';
19
-
20
- import {
21
- getVaultSecretsConfigs,
22
- environmentConfig
23
- } from '../next/config.js';
24
- import { connect } from 'http2';
25
- import { promise } from 'zod';
12
+ import { getVaultSecrets, updateVaultSecrets } from './vault.js';
13
+ import { getVaultSecretsConfigs, environmentConfig } from '../next/config.js';
26
14
 
27
15
  async function ensureDirectoryExists(dirPath) {
28
16
  try {
@@ -33,359 +21,76 @@ async function ensureDirectoryExists(dirPath) {
33
21
  }
34
22
  }
35
23
 
36
- async function copyDirectory(source, destination) {
37
- try {
38
- await fl.mkdir(destination, { recursive: true });
39
- const items = await fl.readdir(source, { withFileTypes: true });
40
-
41
- for (const item of items) {
42
- const sourcePath = path.join(source, item.name);
43
- const destinationPath = path.join(destination, item.name);
44
-
45
- if (item.isDirectory()) {
46
- await copyDirectory(sourcePath, destinationPath);
47
- } else {
48
- await fl.copyFile(sourcePath, destinationPath);
49
- }
50
- }
51
- } catch (err) {
52
- console.error(`Error copying directory: ${err.message}`);
53
- throw err;
54
- }
55
- }
56
-
57
- async function addApplicationToApi ({application, auth0Domain, auth0AuthToken, coreApiIdentifier}){
58
- console.log("Adding application to API authorized applications...");
59
-
24
+ export async function getAuth0AuthToken(auth0Domain, clientId, clientSecret) {
60
25
  try {
61
- const auth0Response = await axios.get(`https://${auth0Domain}/api/v2/clients`, {
62
- headers: {authorization: `Bearer ${auth0AuthToken}`},
63
- });
64
-
65
- const appAuth0ClientIdData = auth0Response.data.find(client => client.name === `${application}`);
66
- const appAuth0ClientId = appAuth0ClientIdData.client_id;
67
-
68
- await axios.post(
69
- `https://${auth0Domain}/api/v2/client-grants`,
26
+ const response = await axios.post(
27
+ `https://${auth0Domain}/oauth/token`,
70
28
  {
71
- client_id: appAuth0ClientId,
72
- audience: `${coreApiIdentifier}`,
73
- scope: [],
29
+ client_id: clientId,
30
+ client_secret: clientSecret,
31
+ audience: `https://${auth0Domain}/api/v2/`,
32
+ grant_type: 'client_credentials',
74
33
  },
75
34
  {
76
35
  headers: {
77
- Authorization: `Bearer ${auth0AuthToken}`,
78
- "Content-Type": "application/json",
36
+ 'Content-Type': 'application/json',
79
37
  },
80
- }
81
- );
82
- console.log(`Application (${appAuth0ClientId}) authorized for API: ${coreApiIdentifier}`);
83
- } catch (err) {
84
- console.error(`Failed to add application: ${application}: ${err.message}`);
85
- }
86
-
87
- }
88
-
89
- async function initializeAuth0Configuration({
90
- initConfiguration,
91
- auth0Domain,
92
- auth0AuthToken,
93
- coreApiIdentifier,
94
- }) {
95
- if (initConfiguration === "true") {
96
- try {
97
- // Create a new resource server in Auth0
98
- console.log("Creating resource server in Auth0...");
99
-
100
- const resourceServerResponse = await axios.post(
101
- `https://${auth0Domain}/api/v2/resource-servers`,
102
- {
103
- name: "docupace-core",
104
- identifier: `${coreApiIdentifier}`,
105
- token_lifetime: 86400,
106
- allow_offline_access: false,
107
- signing_alg: "RS256",
108
- skip_consent_for_verifiable_first_party_clients: true,
109
- scopes: [],
110
- },
111
- {
112
- headers: {
113
- Authorization: `Bearer ${auth0AuthToken}`,
114
- "Content-Type": "application/json",
115
- },
116
- }
117
- );
118
-
119
- const apiId = resourceServerResponse.data.id;
120
-
121
- // Update tenant settings with the default audience
122
- console.log("Updating tenant settings...");
123
- await axios.patch(
124
- `https://${auth0Domain}/api/v2/tenants/settings`,
125
- {
126
- default_audience: `${coreApiIdentifier}`,
127
- },
128
- {
129
- headers: {
130
- Authorization: `Bearer ${auth0AuthToken}`,
131
- "Content-Type": "application/json",
132
- },
133
- }
134
- );
135
- console.log("Tenant settings updated successfully.");
136
- } catch (error) {
137
- console.error("Error during Auth0 configuration:", error.response?.data || error.message);
138
- }
139
- }
140
- }
141
-
142
- async function importAuth0Templates(directoryPath, auth0Domain, auth0ClientID, auth0ClientSecret) {
143
- try {
144
- const config = {
145
- input_file: directoryPath,
146
- config: {
147
- AUTH0_DOMAIN: auth0Domain,
148
- AUTH0_CLIENT_ID: auth0ClientID,
149
- AUTH0_CLIENT_SECRET: auth0ClientSecret,
150
38
  },
151
- debug: true,
152
- };
153
-
154
- console.log('Starting Auth0 template import...');
155
- await deploy(config);
156
- console.log('Auth0 template import completed successfully!');
157
- } catch (error) {
158
- console.error('Error during Auth0 template import:', error.message);
159
- process.exit(1); // Exit with an error code
160
- }
161
- }
162
-
163
- async function updateJsonFile(filePath, updates) {
164
- const content = await fs.promises.readFile(filePath, 'utf8');
165
- const jsonContent = JSON.parse(content);
166
- const updatedContent = JSON.stringify({...jsonContent, ...updates}, null, 2);
167
- await fs.promises.writeFile(filePath, updatedContent);
168
- }
169
-
170
- async function replaceInFile(filePath, replacements) {
171
- let content = await fs.promises.readFile(filePath, 'utf8');
172
-
173
- for (const [search, replace] of replacements) {
174
- const escapedSearch = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); // Escape special chars
175
- content = content.replace(new RegExp(escapedSearch, 'g'), replace);
176
- }
177
- await fs.promises.writeFile(filePath, content, 'utf8');
178
- }
179
-
180
- async function templateAuth0(siteUrl, coreApiContext, env, filePaths, deployUI, deployGraphQLServer, commonSecrets, configureMFA) {
181
- try {
182
- let uiAllowedCallbacksUrls,
183
- uiAllowedLogoutUrls;
184
- let graphqlAllowedCallbacksUrls,
185
- graphqlAllowedLogoutUrls;
186
- let connectAllowedCallbacksUrls,
187
- connectlAllowedLogoutUrls;
188
-
189
- let connectClientMetadata,
190
- connectCallbacks,
191
- connectAddons;
192
- // Configure URLs based on environment
193
- if (env === 'prd') {
194
- uiAllowedCallbacksUrls = [`${siteUrl}/api/auth/callback`];
195
- uiAllowedLogoutUrls = [`${siteUrl}`];
196
-
197
- graphqlAllowedCallbacksUrls = [`${siteUrl}/api/graphql/callback`];
198
- graphqlAllowedLogoutUrls = [`${siteUrl}/api/graphql/`];
199
-
200
- connectAllowedCallbacksUrls = [`${siteUrl}/connect/samlCallback?client_name=auth0`];
201
- connectlAllowedLogoutUrls = [ `${siteUrl}/connect`];
202
- } else {
203
- uiAllowedCallbacksUrls = [
204
- `${siteUrl}/api/auth/callback`,
205
- `http://localhost:3000/api/auth/callback`,
206
- ];
207
- uiAllowedLogoutUrls = [
208
- `${siteUrl}`,
209
- `http://localhost:3000`,
210
- ];
211
- graphqlAllowedCallbacksUrls = [
212
- `${siteUrl}/api/graphql/callback`,
213
- `http://localhost:4000/api/graphql/callback`,
214
- ];
215
- graphqlAllowedLogoutUrls = [
216
- `http://localhost:4000/api/graphql/`,
217
- `${siteUrl}/api/graphql/`,
218
- ];
219
- connectAllowedCallbacksUrls = [
220
- `${siteUrl}/connect/samlCallback?client_name=auth0`,
221
- `http://localhost:9000/connect/samlCallback?client_name=auth0`,
222
- ];
223
- connectlAllowedLogoutUrls = [
224
- `${siteUrl}/connect`
225
- ];
226
-
227
- const siteUrlNoPrefix=siteUrl.replace(/^https?:\/\//, '');
228
- connectClientMetadata ={
229
- "docupaceContext" : "core",
230
- "docupaceHost" : `${siteUrlNoPrefix}`,
231
- "docupace_context" : "core",
232
- "docupace_host" : `${siteUrlNoPrefix} `
233
- };
234
-
235
- connectCallbacks = [
236
- `${siteUrl}/connect/samlCallback?client_name=auth0`
237
- ];
238
-
239
- connectAddons = {
240
- "samlp": {
241
- "audience": `${siteUrl}/connect`,
242
- "recipient": `${siteUrl}/connect/samlCallback?client_name=auth0`,
243
- "destination": `${siteUrl}/connect/samlCallback?client_name=auth0`,
244
- "nameIdentifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
245
- "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
246
- "nameIdentifierProbes": [
247
- "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/docupace-username"
248
- ],
249
- "mappings": {
250
- "proposalHandle": "ProposalHandle"
251
- }
252
- }
253
- };
254
-
255
- }
256
-
257
-
258
- const configureUI = deployUI === 'true';
259
- if (configureUI) {
260
- console.log('ui_allowed_callbacks_urls ->', uiAllowedCallbacksUrls);
261
- console.log('ui_allowed_logout_urls ->', uiAllowedLogoutUrls);
262
-
263
- await updateJsonFile(filePaths.uiJson, {
264
- callbacks: uiAllowedCallbacksUrls,
265
- allowed_logout_urls: uiAllowedLogoutUrls,
266
- });
267
-
268
-
269
- //TODO: move to separate function for connect
270
- console.log('connect_allowed_callbacks_urls ->', connectAllowedCallbacksUrls);
271
- console.log('connect_allowed_logout_urls ->', connectlAllowedLogoutUrls);
272
-
273
- // update allowed callback url
274
- await updateJsonFile(filePaths.connectJson, {
275
- callbacks: connectAllowedCallbacksUrls,
276
- allowed_logout_urls: connectlAllowedLogoutUrls,
277
- client_metadata: connectClientMetadata,
278
- addons: connectAddons
279
- });
280
-
281
-
282
-
283
- console.log('Updated URLs for main UI...');
284
- } else {
285
- await fs.promises.unlink(filePaths.uiJson);
286
- await updateJsonFile(filePaths.databaseJson, {
287
- enabled_clients: (content) => content.enabled_clients.filter((client) => client !== 'docupace-ui-main'),
288
- });
289
- console.log("Removed 'docupace-ui-main' from enabled_clients in database.json");
290
- }
291
-
292
- const configureGraphqlServer = deployGraphQLServer === 'true';
293
- if (configureGraphqlServer) {
294
- console.log('graphql_allowed_callbacks_urls ->', graphqlAllowedCallbacksUrls);
295
- console.log('graphql_allowed_logout_urls ->', graphqlAllowedLogoutUrls);
296
-
297
- await updateJsonFile(filePaths.graphqlJson, {
298
- callbacks: graphqlAllowedCallbacksUrls,
299
- allowed_logout_urls: graphqlAllowedLogoutUrls,
300
- });
301
- console.log('Updated URLs for GraphQL server...');
302
- } else {
303
- await fs.promises.unlink(filePaths.graphqlJson);
304
- await updateJsonFile(filePaths.databaseJson, {
305
- enabled_clients: (content) => content.enabled_clients.filter((client) => client !== 'docupace-graphql'),
306
- });
307
- console.log("Removed 'docupace-graphql' from enabled_clients in database.json");
308
- }
309
-
310
- // TWILIO configuration
311
- await replaceInFile(filePaths.twilioJson, [
312
- ['twilioauthtokenplaceholder', commonSecrets.TWILIO_AUTH_TOKEN],
313
- ['twiliosidplaceholder', commonSecrets.TWILIO_SID],
314
- ['twiliofromplaceholder', commonSecrets.TWILIO_FROM_NUMBER],
315
- ]);
316
-
317
- console.log('TWILIO configuration updated...');
318
-
319
- const tmpSiteUrl = siteUrl.replace(/^https?:\/\//, '');
320
- // Database configuration
321
- await replaceInFile(filePaths.databaseLoginJs, [
322
- ['${docupaceHost}', tmpSiteUrl],
323
- ['${docupaceContext}', coreApiContext],
324
- ]);
325
-
326
- console.log('MFA Template configuration started...');
327
-
328
- try {
329
- const sourceDir = configureMFA === 'DISABLED' ? 'auth0-site-setup/templateNoMFA/' : 'auth0-site-setup/templateMFA/';
330
- const destinationDir = 'auth0-site-setup/template/';
331
-
332
- console.log(`AUTH0 MFA is ${configureMFA === 'DISABLED' ? 'disabled' : 'enabled'}`);
333
- await copyDirectory(sourceDir, destinationDir);
334
-
335
- console.log('MFA configuration completed.');
336
- } catch (err) {
337
- console.error('Error configuring MFA:', err);
338
- throw err;
339
- }
340
-
341
- console.log('Template configuration completed.');
342
- } catch (err) {
343
- // console.error('Error configuring Auth0 templates:', err);
344
- throw err;
345
- }
346
- }
347
-
348
- export async function getAuth0AuthToken(auth0Domain, clientId, clientSecret) {
349
- try {
350
- const response = await axios.post(`https://${auth0Domain}/oauth/token`, {
351
- client_id: clientId,
352
- client_secret: clientSecret,
353
- audience: `https://${auth0Domain}/api/v2/`,
354
- grant_type: 'client_credentials',
355
- }, {
356
- headers: {
357
- 'Content-Type': 'application/json',
358
- },
359
- });
39
+ );
360
40
 
361
41
  const authToken = response.data.access_token;
362
42
  // console.log("Auth0 Auth Token:", authToken);
363
43
  return authToken;
364
44
  } catch (error) {
365
- console.error("Error fetching Auth0 token:", error.response ? error.response.data : error.message);
45
+ console.error(
46
+ 'Error fetching Auth0 token:',
47
+ error.response ? error.response.data : error.message,
48
+ );
366
49
  }
367
50
  }
368
51
 
369
- async function configureUI(siteHost, coreURL, docupaceHost, site, env, useNewDomain, auth0Domain, auth0ClientId, auth0ClientSecret, auth0Token, vaultSiteSecretsPath, imageTag, repoPath) {
370
- console.log(`Configuring UI for site: ${site} Host: ${siteHost} in env: ${env}`);
52
+ async function configureUI(
53
+ siteHost,
54
+ coreURL,
55
+ docupaceHost,
56
+ site,
57
+ env,
58
+ auth0Domain,
59
+ auth0ClientId,
60
+ auth0ClientSecret,
61
+ auth0Token,
62
+ vaultSiteSecretsPath,
63
+ imageTag,
64
+ repoPath,
65
+ ) {
66
+ console.log(
67
+ `Configuring UI for site: ${site} Host: ${siteHost} in env: ${env}`,
68
+ );
371
69
  siteHost = siteHost.replace('https://', '');
372
70
  coreURL = coreURL.replace('https://', '');
373
71
 
374
-
375
72
  try {
376
- const auth0Response = await axios.get(`https://${auth0Domain}/api/v2/clients`, {
377
- headers: {authorization: `Bearer ${auth0Token}`},
378
- });
73
+ const auth0Response = await axios.get(
74
+ `https://${auth0Domain}/api/v2/clients`,
75
+ {
76
+ headers: { authorization: `Bearer ${auth0Token}` },
77
+ },
78
+ );
379
79
 
380
- const uiClient = auth0Response.data.find(client => client.name === "docupace-ui-main");
80
+ const uiClient = auth0Response.data.find(
81
+ (client) => client.name === 'docupace-ui-main',
82
+ );
381
83
  const uiAuth0ClientId = uiClient.client_id;
382
84
  const uiAuth0ClientSecret = uiClient.client_secret;
383
85
 
384
86
  // Generate Auth0 Secret
385
- const uiAuth0Secret = crypto.randomBytes(48).toString('base64').replace(/[^a-zA-Z0-9]/g, '');
87
+ const uiAuth0Secret = crypto
88
+ .randomBytes(48)
89
+ .toString('base64')
90
+ .replace(/[^a-zA-Z0-9]/g, '');
386
91
 
387
92
  // Prepare data payload
388
- console.log("Preparing Vault UI data payload...");
93
+ console.log('Preparing Vault UI data payload...');
389
94
  const uiSecretData = JSON.stringify({
390
95
  data: {
391
96
  AUTH0_CLIENT_ID: uiAuth0ClientId,
@@ -415,6 +120,9 @@ uiMain:
415
120
  env:
416
121
  AUTH0_CLIENT_SECRET: vault:secret/data/${site}/ui/config#AUTH0_CLIENT_SECRET
417
122
  AUTH0_SECRET: vault:secret/data/${site}/ui/config#AUTH0_SECRET
123
+ AWS_ACCESS_KEY_ID: vault:secret/data/${site}/aws/config#AWS_ACCESS_KEY_ID
124
+ AWS_BUCKET_NAME: vault:secret/data/${site}/aws/config#AWS_BUCKET_NAME
125
+ AWS_SECRET_ACCESS_KEY: vault:secret/data/${site}/aws/config#AWS_SECRET_ACCESS_KEY
418
126
  image:
419
127
  repository: registry.paperout.com/docupace-ui-main-dev-docker-local/docupace-ui-main
420
128
  tag: ${imageTag}
@@ -438,7 +146,7 @@ ingress:
438
146
  - ${siteHost}
439
147
  secretName: dp-next-ui-cert
440
148
  externalConnectIngress:
441
- enabled: ${useNewDomain}
149
+ enabled: true
442
150
  className: nginx
443
151
  annotations:
444
152
  cert-manager.io/cluster-issuer: letsencrypt
@@ -467,57 +175,91 @@ externalConnectIngress:
467
175
  - ${siteHost}
468
176
  secretName: dp-next-ui-cert
469
177
  externalConnectService:
470
- enabled: ${useNewDomain}
178
+ enabled: true
471
179
  name: external-connect
472
180
  domain: ${docupaceHost}
473
181
  `.trim();
474
182
 
475
183
  // Write configuration files
476
- console.log("Writing configuration files...");
184
+ console.log('Writing configuration files...');
477
185
  await ensureDirectoryExists(path.resolve(`${repoPath}/dp/${site}`));
478
186
 
479
- await fs.writeFile(`${repoPath}/dp/${site}/ui.app.yaml`, uiAppYaml, (err) => {
480
- if (err) {
481
- console.error("Failed to write the file:", err);
482
- } else {
483
- console.log("File written successfully.");
484
- }
485
- });
187
+ await fs.writeFile(
188
+ `${repoPath}/dp/${site}/ui.app.yaml`,
189
+ uiAppYaml,
190
+ (err) => {
191
+ if (err) {
192
+ console.error('Failed to write the file:', err);
193
+ } else {
194
+ console.log('File written successfully.');
195
+ }
196
+ },
197
+ );
486
198
 
487
- await fs.writeFile(`${repoPath}/dp/${site}/ui.values.yaml`, uiValuesYaml, (err) => {
488
- if (err) {
489
- console.error("Failed to write the file:", err);
490
- } else {
491
- console.log("File written successfully.");
492
- }
493
- });
494
- console.log("Done!");
199
+ await fs.writeFile(
200
+ `${repoPath}/dp/${site}/ui.values.yaml`,
201
+ uiValuesYaml,
202
+ (err) => {
203
+ if (err) {
204
+ console.error('Failed to write the file:', err);
205
+ } else {
206
+ console.log('File written successfully.');
207
+ }
208
+ },
209
+ );
210
+ console.log('Done!');
495
211
  } catch (error) {
496
- console.error("Error configuring UI:", error);
212
+ console.error('Error configuring UI:', error);
497
213
  }
498
214
  }
499
215
 
500
- async function configureGraphQLServer(siteHost, coreURL, docupaceHost, site, env, auth0Domain, auth0ClientId, auth0ClientSecret, auth0Token, vaultSiteSecretsPath, imageTag, standardConfigRemoteBranch, repoPath, commonSecrets) {
216
+ async function configureGraphQLServer(
217
+ siteHost,
218
+ coreURL,
219
+ docupaceHost,
220
+ site,
221
+ env,
222
+ auth0Domain,
223
+ auth0ClientId,
224
+ auth0ClientSecret,
225
+ auth0Token,
226
+ vaultSiteSecretsPath,
227
+ imageTag,
228
+ standardConfigRemoteBranch,
229
+ repoPath,
230
+ commonSecrets,
231
+ ) {
501
232
  siteHost = siteHost.replace('https://', '');
502
233
  coreURL = coreURL.replace('https://', '');
503
- console.log(`Configuring GraphQL Server for site: ${site} Host: ${siteHost} in env: ${env}`);
234
+ console.log(
235
+ `Configuring GraphQL Server for site: ${site} Host: ${siteHost} in env: ${env}`,
236
+ );
504
237
 
505
238
  try {
506
- const auth0Response = await axios.get(`https://${auth0Domain}/api/v2/clients`, {
507
- headers: {authorization: `Bearer ${auth0Token}`},
508
- });
239
+ const auth0Response = await axios.get(
240
+ `https://${auth0Domain}/api/v2/clients`,
241
+ {
242
+ headers: { authorization: `Bearer ${auth0Token}` },
243
+ },
244
+ );
509
245
 
510
- const graphQLServerClient = auth0Response.data.find(client => client.name === "docupace-graphql");
511
- const graphQLServerClientCredentials = auth0Response.data.find(client => client.name === "docupace-graphql-client-credentials");
246
+ const graphQLServerClient = auth0Response.data.find(
247
+ (client) => client.name === 'docupace-graphql',
248
+ );
249
+ const graphQLServerClientCredentials = auth0Response.data.find(
250
+ (client) => client.name === 'docupace-graphql-client-credentials',
251
+ );
512
252
 
513
253
  const graphQLServerAuth0ClientId = graphQLServerClient.client_id;
514
254
  const graphQLServerAuth0ClientSecret = graphQLServerClient.client_secret;
515
255
 
516
- const graphQLServerCCAuth0ClientId = graphQLServerClientCredentials.client_id;
517
- const graphQLServerCCAuth0ClientSecret = graphQLServerClientCredentials.client_secret;
256
+ const graphQLServerCCAuth0ClientId =
257
+ graphQLServerClientCredentials.client_id;
258
+ const graphQLServerCCAuth0ClientSecret =
259
+ graphQLServerClientCredentials.client_secret;
518
260
 
519
261
  // Prepare data payload
520
- console.log("Preparing Vault GraphQL Server data payload...");
262
+ console.log('Preparing Vault GraphQL Server data payload...');
521
263
  const graphQLServerSecretData = JSON.stringify({
522
264
  data: {
523
265
  AUTH0_CLIENT_ID: graphQLServerAuth0ClientId,
@@ -580,105 +322,128 @@ ingress:
580
322
  `.trim();
581
323
 
582
324
  // Write configuration files
583
- console.log("Writing ArgoCD GraphQL Server configuration files...");
325
+ console.log('Writing ArgoCD GraphQL Server configuration files...');
584
326
  await ensureDirectoryExists(path.resolve(`${repoPath}/dp/${site}`));
585
327
 
586
- await fs.writeFile(`${repoPath}/dp/${site}/graphql-server.app.yaml`, graphQLServerAppYaml, (err) => {
587
- if (err) {
588
- console.error("Failed to write the file:", err);
589
- } else {
590
- console.log("File written successfully.");
591
- }
592
- });
328
+ await fs.writeFile(
329
+ `${repoPath}/dp/${site}/graphql-server.app.yaml`,
330
+ graphQLServerAppYaml,
331
+ (err) => {
332
+ if (err) {
333
+ console.error('Failed to write the file:', err);
334
+ } else {
335
+ console.log('File written successfully.');
336
+ }
337
+ },
338
+ );
593
339
 
594
- await fs.writeFile(`${repoPath}/dp/${site}/graphql-server.values.yaml`, graphQLServerValuesYaml, (err) => {
595
- if (err) {
596
- console.error("Failed to write the file:", err);
597
- } else {
598
- console.log("File written successfully.");
599
- }
600
- });
601
- console.log("Done!");
340
+ await fs.writeFile(
341
+ `${repoPath}/dp/${site}/graphql-server.values.yaml`,
342
+ graphQLServerValuesYaml,
343
+ (err) => {
344
+ if (err) {
345
+ console.error('Failed to write the file:', err);
346
+ } else {
347
+ console.log('File written successfully.');
348
+ }
349
+ },
350
+ );
351
+ console.log('Done!');
602
352
  } catch (error) {
603
- console.error("Error configuring GraphQL Server:", error);
353
+ console.error('Error configuring GraphQL Server:', error);
604
354
  }
605
355
  }
606
356
 
607
-
608
- export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployUI, deployGraphQLServer, useNewDomain, configureMFA) {
609
- console.log(`Configuring Auth0 tenants and ArgoCD apps for site: ${toSite} in env: ${toEnv} from site: ${fromSite}`);
357
+ export async function configureFromSite(
358
+ fromSite,
359
+ toSite,
360
+ fromEnv,
361
+ toEnv,
362
+ deployUI,
363
+ deployGraphQLServer,
364
+ useNewDomain,
365
+ ) {
366
+ console.log(
367
+ `Configuring Auth0 tenants and ArgoCD apps for site: ${toSite} in env: ${toEnv} from site: ${fromSite}`,
368
+ );
610
369
  // Common Secrets
611
370
  const commonSecretsPath = getVaultSecretsConfigs(toSite).commonSecretsPath;
612
- console.log(`commonSecretsPath => ${commonSecretsPath}`)
371
+ console.log(`commonSecretsPath => ${commonSecretsPath}`);
613
372
  const commonSecrets = await getVaultSecrets(commonSecretsPath);
614
373
 
615
374
  // Site Common Secrets
616
- const siteCommonSecretsPath = getVaultSecretsConfigs(toSite).siteCommonSecretsPath;
617
- console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`)
375
+ const siteCommonSecretsPath =
376
+ getVaultSecretsConfigs(toSite).siteCommonSecretsPath;
377
+ console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`);
618
378
  const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
619
379
 
620
- const auth0Domain = `docupace-${toEnv}-${toSite}.us.auth0.com`
380
+ const auth0Domain = `docupace-${toEnv}-${toSite}.us.auth0.com`;
621
381
  const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
622
382
  const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
623
- const auth0Token = await getAuth0AuthToken(auth0Domain, auth0ClientId, auth0ClientSecret);
383
+ const auth0Token = await getAuth0AuthToken(
384
+ auth0Domain,
385
+ auth0ClientId,
386
+ auth0ClientSecret,
387
+ );
624
388
 
625
389
  // UI app
626
390
  const uiSecretsPath = getVaultSecretsConfigs(toSite).uiSecretsPath;
627
- console.log(`uiSecretsPath => ${uiSecretsPath}`)
391
+ console.log(`uiSecretsPath => ${uiSecretsPath}`);
628
392
 
629
393
  // GraphQL-Server app
630
- const graphqlSecretsPath = getVaultSecretsConfigs(toSite).graphqlServerSecretsPath;
394
+ const graphqlSecretsPath =
395
+ getVaultSecretsConfigs(toSite).graphqlServerSecretsPath;
631
396
  console.log(`graphqlSecretsPath => ${graphqlSecretsPath}`);
632
397
 
633
- let repoPathFromEnv ="";
634
- let repoPathToEnv = "";
398
+ let repoPathFromEnv = '';
399
+ let repoPathToEnv = '';
635
400
  // Clone repositories
636
- if ( fromEnv == toEnv ) {
637
- repoPathFromEnv = await cloneEnvRepository(fromEnv);
638
- repoPathToEnv = repoPathFromEnv;
639
- }else {
640
- repoPathFromEnv = await cloneEnvRepository(fromEnv);
641
- repoPathToEnv = await cloneEnvRepository(toEnv);
401
+ if (fromEnv === toEnv) {
402
+ repoPathFromEnv = await cloneEnvRepository(fromEnv);
403
+ repoPathToEnv = repoPathFromEnv;
404
+ } else {
405
+ repoPathFromEnv = await cloneEnvRepository(fromEnv);
406
+ repoPathToEnv = await cloneEnvRepository(toEnv);
642
407
  }
643
408
 
644
409
  //TODO: clone fromEnv and toEnv. replace above with this
645
410
 
646
- const auth0RepoPath = await cloneRepository('auth0-site-setup');
411
+ // const auth0RepoPath = await cloneRepository('auth0-site-setup');
647
412
 
648
413
  // Read deploy configs
649
- const { deployConfig: deployUIConfig } = await readDeployConfig('ui', fromEnv, fromSite, 'values');
414
+ const { deployConfig: deployUIConfig } = await readDeployConfig(
415
+ 'ui',
416
+ fromEnv,
417
+ fromSite,
418
+ 'values',
419
+ );
650
420
  const uiImageTag = deployUIConfig.image.tag;
651
421
 
652
- const { deployConfig: deployGraphQLServerConfig } = await readDeployConfig('graphql-server', fromEnv, fromSite, 'values');
422
+ const { deployConfig: deployGraphQLServerConfig } = await readDeployConfig(
423
+ 'graphql-server',
424
+ fromEnv,
425
+ fromSite,
426
+ 'values',
427
+ );
653
428
  const graphqlImageTag = deployGraphQLServerConfig.image.tag;
654
- const graphqlStandardConfigRemoteBranch = deployGraphQLServerConfig.graphqlServer.standardConfigRemoteBranch;
655
-
656
- // File paths
657
- const filePaths = {
658
- databaseLoginJs: './auth0-site-setup/template/database-connections/docupace/login.js',
659
- loginHtml: './auth0-site-setup/template/pages/login.html',
660
- graphqlJson: './auth0-site-setup/template/clients/docupace-graphql.json',
661
- uiJson: './auth0-site-setup/template/clients/docupace-ui-main.json',
662
- connectJson: './auth0-site-setup/template/clients/docupace-connect.json',
663
- databaseJson: './auth0-site-setup/template/database-connections/docupace/database.json',
664
- twilioJson: './auth0-site-setup/template/guardian/providers/sms-twilio.json',
665
- };
666
-
667
- console.log(`Copying Latest UI Image Tag: ${deployUIConfig.image.tag} from site: ${fromSite} to site: ${toSite}`);
668
- console.log(`Copying Latest GraphQL Server Image Tag: ${deployGraphQLServerConfig.image.tag} from site: ${fromSite} to site: ${toSite}`);
429
+ const graphqlStandardConfigRemoteBranch =
430
+ deployGraphQLServerConfig.graphqlServer.standardConfigRemoteBranch;
431
+
432
+ console.log(
433
+ `Copying Latest UI Image Tag: ${deployUIConfig.image.tag} from site: ${fromSite} to site: ${toSite}`,
434
+ );
435
+ console.log(
436
+ `Copying Latest GraphQL Server Image Tag: ${deployGraphQLServerConfig.image.tag} from site: ${fromSite} to site: ${toSite}`,
437
+ );
669
438
 
670
439
  const envConfig = environmentConfig[toEnv];
671
440
 
672
- let CORE_URL,
673
- SITE_HOST,
674
- CORE_API_CONTEXT,
675
- CONNECT_URL,
676
- DOCUPACE_HOST;
441
+ let CORE_URL, SITE_HOST, CORE_API_CONTEXT, CONNECT_URL, DOCUPACE_HOST;
677
442
  if (useNewDomain) {
678
443
  const newUrl = envConfig.newUrl(toSite);
679
444
  CORE_URL = `${newUrl}/core`;
680
445
  SITE_HOST = newUrl;
681
- CORE_API_CONTEXT = "core";
446
+ CORE_API_CONTEXT = 'core';
682
447
  CONNECT_URL = `${newUrl}/connect`;
683
448
  DOCUPACE_HOST = envConfig.docupaceHost();
684
449
  } else {
@@ -689,27 +454,41 @@ export async function configureFromSite(fromSite, toSite, fromEnv,toEnv, deployU
689
454
  CONNECT_URL = `${oldUrl}_ui`;
690
455
  }
691
456
 
692
- await templateAuth0(SITE_HOST, CORE_API_CONTEXT, toEnv, filePaths, deployUI, deployGraphQLServer, commonSecrets, configureMFA);
693
- await importAuth0Templates('./auth0-site-setup/template', auth0Domain, auth0ClientId, auth0ClientSecret);
694
-
695
- if (deployUI === 'true') {
696
- await configureUI(SITE_HOST, CORE_URL, DOCUPACE_HOST, toSite, toEnv, useNewDomain, auth0Domain, auth0ClientId, auth0ClientSecret, auth0Token, uiSecretsPath, uiImageTag, repoPathToEnv);
457
+ if (deployUI === true || deployUI === 'true') {
458
+ await configureUI(
459
+ SITE_HOST,
460
+ CORE_URL,
461
+ DOCUPACE_HOST,
462
+ toSite,
463
+ toEnv,
464
+ auth0Domain,
465
+ auth0ClientId,
466
+ auth0ClientSecret,
467
+ auth0Token,
468
+ uiSecretsPath,
469
+ uiImageTag,
470
+ repoPathToEnv,
471
+ );
697
472
  }
698
473
 
699
- await configureGraphQLServer(SITE_HOST, CORE_URL, DOCUPACE_HOST, toSite, toEnv, auth0Domain, auth0ClientId, auth0ClientSecret, auth0Token, graphqlSecretsPath, graphqlImageTag, graphqlStandardConfigRemoteBranch, repoPathToEnv, commonSecrets);
700
- await pushDeployConfig(repoPathToEnv, `Config update for ${toSite} from ${fromSite} with UI: ${uiImageTag} and GraphQL: ${graphqlImageTag}`);
701
-
702
- await initializeAuth0Configuration({
703
- initConfiguration: "true",
704
- auth0Domain: auth0Domain,
705
- auth0AuthToken: auth0Token,
706
- coreApiIdentifier: commonSecrets.CORE_API_IDENTIFIER,
707
- });
708
-
709
- await addApplicationToApi({
710
- application: 'docupace-graphql-client-credentials',
711
- auth0Domain: auth0Domain,
712
- auth0AuthToken: auth0Token,
713
- coreApiIdentifier: commonSecrets.CORE_API_IDENTIFIER
714
- })
474
+ await configureGraphQLServer(
475
+ SITE_HOST,
476
+ CORE_URL,
477
+ DOCUPACE_HOST,
478
+ toSite,
479
+ toEnv,
480
+ auth0Domain,
481
+ auth0ClientId,
482
+ auth0ClientSecret,
483
+ auth0Token,
484
+ graphqlSecretsPath,
485
+ graphqlImageTag,
486
+ graphqlStandardConfigRemoteBranch,
487
+ repoPathToEnv,
488
+ commonSecrets,
489
+ );
490
+ await pushDeployConfig(
491
+ repoPathToEnv,
492
+ `Config update for ${toSite} from ${fromSite} with UI: ${uiImageTag} and GraphQL: ${graphqlImageTag}`,
493
+ );
715
494
  }
@@ -0,0 +1,43 @@
1
+ import { getVaultSecrets } from './vault.js';
2
+ import { getVaultSecretsConfigs } from '../next/config.js';
3
+ import { dump } from 'auth0-deploy-cli';
4
+
5
+ export async function exportConf(site, env) {
6
+ try {
7
+ console.log(
8
+ `Exporting Auth0 configuration for site: ${site} and env: ${env}`,
9
+ );
10
+
11
+ const siteCommonSecretsPath =
12
+ getVaultSecretsConfigs(site).siteCommonSecretsPath;
13
+ console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`);
14
+ const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
15
+
16
+ const auth0Domain = `docupace-${env}-${site}.us.auth0.com`;
17
+ const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
18
+ const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
19
+
20
+ const config = {
21
+ config: {
22
+ AUTH0_DOMAIN: auth0Domain,
23
+ AUTH0_CLIENT_ID: auth0ClientId,
24
+ AUTH0_CLIENT_SECRET: auth0ClientSecret,
25
+ },
26
+ format: 'directory',
27
+ output_folder: `./auth0-${site}-export`,
28
+ export_ids: false,
29
+ env: false,
30
+ debug: true,
31
+ };
32
+
33
+ console.log(`Starting Auth0 ${site} configuration export...`);
34
+ await dump(config);
35
+ console.log(`Auth0 ${site} configuration export completed successfully!`);
36
+ } catch (error) {
37
+ console.error(
38
+ `Error during Auth0 ${site} configuration export:`,
39
+ error.message,
40
+ );
41
+ process.exit(1);
42
+ }
43
+ }
@@ -0,0 +1,132 @@
1
+ import fs from 'fs-extra';
2
+ import axios from 'axios';
3
+ import path from 'path';
4
+ import { cloneRepository } from '../next/deploy.js';
5
+ import { getAuth0AuthToken } from './configure.js';
6
+ import { getVaultSecrets } from './vault.js';
7
+ import { getVaultSecretsConfigs } from '../next/config.js';
8
+ import { pushDeployConfig } from '../next/deploy.js';
9
+
10
+ export async function getAuth0Metadata(site, env) {
11
+ try {
12
+ const connectDeployRepoPath = await cloneRepository('connect-deploy');
13
+
14
+ if (env === 'qa') {
15
+ console.log(
16
+ `The environment is: (${env}), but connect-deploy has preprod instead`,
17
+ );
18
+ process.chdir(`${connectDeployRepoPath}/envs/preprod/${site}`);
19
+ } else {
20
+ process.chdir(`${connectDeployRepoPath}/envs/${env}/${site}`);
21
+ }
22
+
23
+ const configPath = path.join('conf', 'application.conf');
24
+ const appConf = await fs.readFile(configPath, 'utf-8');
25
+ const connectContext = appConf.match(
26
+ /application\.context\s*=\s*"(.*?)"/,
27
+ )?.[1];
28
+
29
+ if (!connectContext) {
30
+ console.error('connectContext not found in application.conf. Exiting...');
31
+ process.exit(1);
32
+ }
33
+
34
+ const siteHost = appConf.match(
35
+ /docupace\.baseUrlClient\s*=\s*"?https?:\/\/([^/]+)"?/,
36
+ )?.[1];
37
+
38
+ if (!siteHost) {
39
+ console.error('siteHost not found in application.conf. Exiting...');
40
+ process.exit(1);
41
+ }
42
+
43
+ const connectEndpoint = `https://${siteHost}${connectContext}`;
44
+ console.log('CONNECT_ENDPOINT:', connectEndpoint);
45
+
46
+ console.log('Requesting token from Auth0...');
47
+ const siteCommonSecretsPath =
48
+ getVaultSecretsConfigs(site).siteCommonSecretsPath;
49
+ console.log(`siteCommonSecretsPath => ${siteCommonSecretsPath}`);
50
+ const siteCommonSecrets = await getVaultSecrets(siteCommonSecretsPath);
51
+ const auth0Domain = `docupace-${env}-${site}.us.auth0.com`;
52
+ const auth0ClientId = siteCommonSecrets.AUTH0_CLIENT_ID;
53
+ const auth0ClientSecret = siteCommonSecrets.AUTH0_CLIENT_SECRET;
54
+ const auth0Token = await getAuth0AuthToken(
55
+ auth0Domain,
56
+ auth0ClientId,
57
+ auth0ClientSecret,
58
+ );
59
+
60
+ const auth0Response = await axios.get(
61
+ `https://${auth0Domain}/api/v2/clients`,
62
+ {
63
+ headers: { authorization: `Bearer ${auth0Token}` },
64
+ },
65
+ );
66
+
67
+ const connectClient = auth0Response.data.find(
68
+ (client) => client.name === 'docupace-connect',
69
+ );
70
+
71
+ if (!connectClient) {
72
+ console.error('Client "docupace-connect" not found.');
73
+ process.exit(1);
74
+ }
75
+
76
+ const clientId = connectClient.client_id;
77
+ console.log('Found client_id:', clientId);
78
+
79
+ const metadataRes = await axios.get(
80
+ `https://${auth0Domain}/samlp/metadata/${clientId}`,
81
+ {
82
+ responseType: 'text',
83
+ },
84
+ );
85
+
86
+ const metadata = metadataRes.data;
87
+
88
+ if (metadata.length < 2000) {
89
+ console.error(
90
+ 'Downloaded metadata looks incorrect (too small). Exiting...',
91
+ );
92
+ process.exit(1);
93
+ }
94
+ await fs.ensureDir('conf/saml');
95
+ await fs.writeFile('conf/saml/auth0.xml', metadata);
96
+ console.log('SAML metadata written to conf/saml/auth0.xml');
97
+
98
+ let newConfig = appConf;
99
+
100
+ if (/useSAML\s*=/.test(appConf)) {
101
+ newConfig = newConfig.replace(/useSAML\s*=.*/, 'useSAML=true');
102
+ } else {
103
+ newConfig += '\nuseSAML=true';
104
+ }
105
+
106
+ const replacements = {
107
+ 'saml.clients.auth0.idpMetadataPath': '${samlEnvPath}"/auth0.xml"',
108
+ 'saml.clients.auth0.spEntityId': `"${connectEndpoint}"`,
109
+ 'saml.clients.auth0.redirectFormInput': '"RelayState"',
110
+ 'saml.clients.auth0.idpLoginUrl': `"https://${auth0Domain}/v2/logout?client_id=${clientId}&returnTo=${connectEndpoint}"`,
111
+ };
112
+
113
+ for (const [key, value] of Object.entries(replacements)) {
114
+ const pattern = new RegExp(`${key}\\s*=.*`, 'g');
115
+ if (pattern.test(newConfig)) {
116
+ newConfig = newConfig.replace(pattern, `${key}=${value}`);
117
+ } else {
118
+ newConfig += `\n${key}=${value}`;
119
+ }
120
+ }
121
+
122
+ await fs.writeFile(configPath, newConfig);
123
+ console.log('The application.conf has been updated.');
124
+ await pushDeployConfig(
125
+ connectDeployRepoPath,
126
+ `Auth0 SAML metadata update for site: (${site}) in env: (${env})`,
127
+ );
128
+ } catch (error) {
129
+ console.error('Error:', error.message);
130
+ process.exit(1);
131
+ }
132
+ }
@@ -44,7 +44,7 @@ export async function getVaultSecrets(vaultPath) {
44
44
  } catch (error) {
45
45
  if (error.response) {
46
46
  console.error(
47
- `Error: Failed to connect to Vault server at ${vaultAddr}. Response: ${error.response.status} ${error.response.statusText}`
47
+ `Error: Failed to connect to Vault server at ${vaultAddr}. Response: ${error.response.status} ${error.response.statusText}`,
48
48
  );
49
49
  } else {
50
50
  console.error(`Error: ${error.message}`);
@@ -88,7 +88,7 @@ export async function updateVaultSecrets(vaultPath, secretData) {
88
88
  'X-Vault-Token': vaultToken,
89
89
  'Content-Type': 'application/json',
90
90
  },
91
- }
91
+ },
92
92
  );
93
93
 
94
94
  // Return the response from Vault
@@ -97,7 +97,7 @@ export async function updateVaultSecrets(vaultPath, secretData) {
97
97
  } catch (error) {
98
98
  if (error.response) {
99
99
  console.error(
100
- `Error: Failed to update secret at ${vaultPath}. Response: ${error.response.status} ${error.response.statusText}`
100
+ `Error: Failed to update secret at ${vaultPath}. Response: ${error.response.status} ${error.response.statusText}`,
101
101
  );
102
102
  } else {
103
103
  console.error(`Error: ${error.message}`);
package/terraform/init.sh CHANGED
@@ -33,16 +33,28 @@ echo "$atlassian_workspace_runner_ssh_key" | base64 -d > ~/.ssh/id_ed25519
33
33
  chmod 600 ~/.ssh/id_ed25519
34
34
  ssh-keyscan bitbucket.org > ~/.ssh/known_hosts
35
35
 
36
-
36
+ info () {
37
+ echo "PROJECT => $PROJECT"
38
+ echo "CURRENT_ENVIRONMENT => $CURRENT_ENVIRONMENT"
39
+ echo "SITE_NAME => $SITE_NAME"
40
+ }
37
41
 
38
42
  if [[ "$PROJECT" == "s3" ]]; then
39
- terraform init \
40
- -input=false \
41
- -reconfigure \
42
- -backend=true \
43
- -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars \
44
- -backend-config="key=us-west-2/${PROJECT}/${SITE_NAME}/${CURRENT_ENVIRONMENT}/terraform.tfstate"
45
-
43
+ info
44
+ terraform init \
45
+ -input=false \
46
+ -reconfigure \
47
+ -backend=true \
48
+ -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars \
49
+ -backend-config="key=us-west-2/${PROJECT}/${SITE_NAME}/${CURRENT_ENVIRONMENT}/terraform.tfstate"
50
+ elif [[ "$PROJECT" == "idp" ]]; then
51
+ info
52
+ terraform init \
53
+ -input=false \
54
+ -reconfigure \
55
+ -backend=true \
56
+ -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars \
57
+ -backend-config="key=us-west-2/${PROJECT}/${SITE_NAME}/${CURRENT_ENVIRONMENT}/terraform.tfstate"
46
58
  else
47
59
  terraform init -backend-config=./env/${CURRENT_ENVIRONMENT}/us-west-2/backend.tfvars --reconfigure
48
- fi
60
+ fi
package/terraform/plan.sh CHANGED
@@ -44,11 +44,18 @@ elif [[ "$PROJECT" == "s3" ]];then
44
44
  -var="site=${SITE_NAME}" \
45
45
  -var="env=${CURRENT_ENVIRONMENT}" \
46
46
  -out .tfplan
47
+ elif [[ "$PROJECT" == "idp" ]];then
48
+ terraform plan -var-file="./env/${CURRENT_ENVIRONMENT}/us-west-2/terraform.tfvars" \
49
+ -var="site=${SITE_NAME}" \
50
+ -var="env=${CURRENT_ENVIRONMENT}" \
51
+ -var="docupace_domain=${DOCUPACE_DOMAIN}" \
52
+ -var="docupace_next_domain=${DOCUPACE_NEXT_DOMAIN}" \
53
+ -var="old_page_design=${USE_OLD_PAGE_DESIGN}" \
54
+ -var="use_new_domain=${USE_NEW_DOMAIN}" \
55
+ -var="configure_autologin=${CONFIGURE_AUTOLOGIN}" \
56
+ -var="configure_ui_main=${CONFIGURE_UI_MAIN}" \
57
+ -var="enable_mfa=${ENABLE_MFA}" \
58
+ -out .tfplan
47
59
  else
48
60
  terraform plan -var-file="./env/${CURRENT_ENVIRONMENT}/us-west-2/terraform.tfvars" -out .tfplan
49
61
  fi
50
-
51
-
52
-
53
-
54
-