@rockcarver/frodo-cli 4.0.0-11 → 4.0.0-12

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/CHANGELOG.md CHANGED
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.0.0-11] - 2026-02-24
11
+
10
12
  ## [4.0.0-10] - 2026-02-23
11
13
 
12
14
  ## [4.0.0-9] - 2026-02-23
@@ -2183,7 +2185,8 @@ Frodo CLI 2.x automatically refreshes session and access tokens before they expi
2183
2185
  - Fixed problem with adding connection profiles
2184
2186
  - Miscellaneous bug fixes
2185
2187
 
2186
- [unreleased]: https://github.com/rockcarver/frodo-cli/compare/v4.0.0-10...HEAD
2188
+ [unreleased]: https://github.com/rockcarver/frodo-cli/compare/v4.0.0-11...HEAD
2189
+ [4.0.0-11]: https://github.com/rockcarver/frodo-cli/compare/v4.0.0-10...v4.0.0-11
2187
2190
  [4.0.0-10]: https://github.com/rockcarver/frodo-cli/compare/v4.0.0-9...v4.0.0-10
2188
2191
  [4.0.0-9]: https://github.com/rockcarver/frodo-cli/compare/v4.0.0-8...v4.0.0-9
2189
2192
  [4.0.0-8]: https://github.com/rockcarver/frodo-cli/compare/v4.0.0-7...v4.0.0-8
package/dist/app.cjs CHANGED
@@ -28757,6 +28757,12 @@ var require_Client = __commonJS2({
28757
28757
  async _downloadFromWorkingDir(localDirPath) {
28758
28758
  await ensureLocalDirectory(localDirPath);
28759
28759
  for (const file of await this.list()) {
28760
+ const hasInvalidName = !file.name || (0, path_1.basename)(file.name) !== file.name;
28761
+ if (hasInvalidName) {
28762
+ const safeName = JSON.stringify(file.name);
28763
+ this.ftp.log(`Invalid filename from server listing, will skip file. (${safeName})`);
28764
+ continue;
28765
+ }
28760
28766
  const localPath = (0, path_1.join)(localDirPath, file.name);
28761
28767
  if (file.isDirectory) {
28762
28768
  await this.cd(file.name);
@@ -141687,54 +141693,70 @@ var AVAILABLE_SCOPES = {
141687
141693
  AMIntrospectAllTokensAnyRealm: "am-introspect-all-tokens-any-realm",
141688
141694
  OpenIdScope: "openid",
141689
141695
  ProfileScope: "profile",
141690
- // All Access Management APIs
141691
141696
  AmFullScope: "fr:am:*",
141692
- // All Auto Access APIs
141697
+ // All Access Management APIs
141693
141698
  AutoAccessFullScope: "fr:autoaccess:*",
141694
- // All Analytics APIs
141699
+ // All Auto Access APIs
141695
141700
  AnalyticsFullScope: "fr:idc:analytics:*",
141696
- // All TLS certificate APIs
141701
+ // All Analytics APIs
141697
141702
  CertificateFullScope: "fr:idc:certificate:*",
141698
- // Read TLS certificates
141703
+ // All TLS certificate APIs
141699
141704
  CertificateReadScope: "fr:idc:certificate:read",
141700
- // All content security policy APIs
141705
+ // Read TLS certificates
141701
141706
  ContentSecurityPolicyFullScope: "fr:idc:content-security-policy:*",
141702
- // All cookie domain APIs
141707
+ // All content security policy APIs
141708
+ ContentSecurityPolicyReadScope: "fr:idc:content-security-policy:read",
141709
+ // Read content security policy
141703
141710
  CookieDomainsFullScope: "fr:idc:cookie-domain:*",
141704
- // All custom domain APIs
141711
+ // All cookie domain APIs
141712
+ CookieDomainsReadScope: "fr:idc:cookie-domain:read",
141713
+ // Read cookie domain APIs
141705
141714
  CustomDomainFullScope: "fr:idc:custom-domain:*",
141706
- // All dataset deletion APIs
141715
+ // All custom domain APIs
141716
+ CustomDomainReadScope: "fr:idc:custom-domain:read",
141717
+ // Read custom domain configuration
141707
141718
  DatasetDeletionFullScope: "fr:idc:dataset:*",
141708
- // All ESV APIs
141719
+ // All dataset deletion APIs
141720
+ DatasetDeletionReadScope: "fr:idc:dataset:read",
141721
+ // Read dataset deletion configuration
141709
141722
  ESVFullScope: "fr:idc:esv:*",
141710
- // Read ESVs, excluding values of secrets
141723
+ // All ESV APIs
141711
141724
  ESVReadScope: "fr:idc:esv:read",
141712
- // Create, modify, and delete ESVs
141725
+ // Read ESVs, excluding values of secrets
141713
141726
  ESVUpdateScope: "fr:idc:esv:update",
141714
- // Restart workloads that consume ESVs
141727
+ // Create, modify, and delete ESVs
141715
141728
  ESVRestartScope: "fr:idc:esv:restart",
141716
- // Create, modify, and delete Admin Federation configuration
141729
+ // Restart workloads that consume ESVs
141717
141730
  AdminFederationFullScope: "fr:idc:federation:*",
141718
- // Read Admin Federation configuration
141731
+ // Create, modify, and delete Admin Federation configuration
141719
141732
  AdminFederationReadScope: "fr:idc:federation:read",
141720
- // All mTLS APIs
141733
+ // Read Admin Federation configuration
141721
141734
  MTLSFullScope: "fr:idc:mtls:*",
141722
- // All configuration promotion APIs
141735
+ // All mTLS APIs
141723
141736
  PromotionScope: "fr:idc:promotion:*",
141724
- // All Proxy Connect APIs
141737
+ // All configuration promotion APIs
141738
+ PromotionReadScope: "fr:idc:promotion:read",
141739
+ // Read configuration promotion configuration
141725
141740
  ProxyConnectFullScope: "fr:idc:proxy-connect:*",
141726
- // Read Proxy Connect configuration
141741
+ // All Proxy Connect APIs
141727
141742
  ProxyConnectReadScope: "fr:idc:proxy-connect:read",
141728
- // Create and update Proxy Connect configuration
141743
+ // Read Proxy Connect configuration
141729
141744
  ProxyConnectWriteScope: "fr:idc:proxy-connect:write",
141730
- // All product release APIs
141745
+ // Create and update Proxy Connect configuration
141731
141746
  ReleaseFullScope: "fr:idc:release:*",
141732
- // All SSO cookie APIs
141747
+ // All product release APIs
141748
+ ReleaseReadScope: "fr:idc:release:read",
141749
+ // Read product release information
141733
141750
  SSOCookieFullScope: "fr:idc:sso-cookie:*",
141734
- // All Identity Management APIs
141751
+ // All SSO cookie APIs
141752
+ SSOCookieReadScope: "fr:idc:sso-cookie:read",
141753
+ // Read SSO cookie configuration
141754
+ WSFedAdminScope: "fr:idc:ws:admin",
141755
+ // All PingFederate APIs
141735
141756
  IdmFullScope: "fr:idm:*",
141736
- // All Governance APIs
141757
+ // All Identity Management APIs
141737
141758
  IGAFullScope: "fr:iga:*"
141759
+ // All Governance APIs
141738
141760
  };
141739
141761
  var RETRY_EVERYTHING_KEY = "everything";
141740
141762
  var RETRY_NETWORK_KEY = "network";
@@ -142000,7 +142022,7 @@ function stringify(obj) {
142000
142022
  }
142001
142023
  var package_default = {
142002
142024
  name: "@rockcarver/frodo-lib",
142003
- version: "4.0.0-11",
142025
+ version: "4.0.0-12",
142004
142026
  type: "commonjs",
142005
142027
  main: "./dist/index.js",
142006
142028
  module: "./dist/index.mjs",
@@ -142256,6 +142278,12 @@ var State_default = (initialState) => {
142256
142278
  getAuthenticationService() {
142257
142279
  return state2.authenticationService || process.env.FRODO_AUTHENTICATION_SERVICE;
142258
142280
  },
142281
+ setConfigurationHeaderOverrides(overrides) {
142282
+ state2.configurationHeaderOverrides = overrides;
142283
+ },
142284
+ getConfigurationHeaderOverrides() {
142285
+ return state2.configurationHeaderOverrides;
142286
+ },
142259
142287
  setServiceAccountId(uuid) {
142260
142288
  state2.serviceAccountId = uuid;
142261
142289
  },
@@ -142501,6 +142529,7 @@ var logger = import_winston.default.createLogger({
142501
142529
  });
142502
142530
  var globalState = {
142503
142531
  authenticationHeaderOverrides: {},
142532
+ configurationHeaderOverrides: {},
142504
142533
  printHandler: (message) => {
142505
142534
  if (!message) return;
142506
142535
  if (typeof message === "object") {
@@ -160550,6 +160579,57 @@ function generateAmApi({
160550
160579
  resource,
160551
160580
  requestOverride = {},
160552
160581
  state: state2
160582
+ }) {
160583
+ const headers2 = {
160584
+ "User-Agent": userAgent,
160585
+ "X-ForgeRock-TransactionId": transactionId,
160586
+ "Content-Type": "application/json",
160587
+ // only add API version if we have it
160588
+ ...resource.apiVersion && { "Accept-API-Version": resource.apiVersion },
160589
+ // only send session cookie if we know its name and value and we are not instructed to use the bearer token for AM APIs
160590
+ ...!state2.getUseBearerTokenForAmApis() && state2.getCookieName() && state2.getCookieValue() && {
160591
+ Cookie: `${state2.getCookieName()}=${state2.getCookieValue()}`
160592
+ },
160593
+ // only add authorization header if we have a bearer token and are instructed to use it for AM APIs
160594
+ ...state2.getUseBearerTokenForAmApis() && state2.getBearerToken() && {
160595
+ Authorization: `Bearer ${state2.getBearerToken()}`
160596
+ }
160597
+ };
160598
+ const requestConfig = mergeDeep(
160599
+ {
160600
+ // baseURL: `${storage.session.getTenant()}/json`,
160601
+ timeout: timeout3,
160602
+ headers: {
160603
+ ...headers2,
160604
+ ...state2.getAuthenticationHeaderOverrides(),
160605
+ ...state2.getConfigurationHeaderOverrides()
160606
+ },
160607
+ ...process.env.FRODO_MOCK !== "record" && process.env.FRODO_POLLY_MODE !== "record" && {
160608
+ httpAgent: getHttpAgent(),
160609
+ httpsAgent: getHttpsAgent(state2.getAllowInsecureConnection())
160610
+ },
160611
+ proxy: getProxy()
160612
+ },
160613
+ requestOverride
160614
+ );
160615
+ debugMessage({
160616
+ message: `Generating AM API client for resource with request headers ${JSON.stringify(
160617
+ requestConfig.headers,
160618
+ null,
160619
+ 2
160620
+ )}`,
160621
+ state: state2
160622
+ });
160623
+ const request = createAxiosInstance(state2, requestConfig);
160624
+ if (state2.getCurlirize()) {
160625
+ curlirize(request, state2);
160626
+ }
160627
+ return request;
160628
+ }
160629
+ function generateAmAuthApi({
160630
+ resource,
160631
+ requestOverride = {},
160632
+ state: state2
160553
160633
  }) {
160554
160634
  const headers2 = {
160555
160635
  "User-Agent": userAgent,
@@ -160659,6 +160739,7 @@ function generateIdmApi({
160659
160739
  "X-ForgeRock-TransactionId": transactionId,
160660
160740
  "Content-Type": "application/json",
160661
160741
  ...state2.getAuthenticationHeaderOverrides(),
160742
+ ...state2.getConfigurationHeaderOverrides(),
160662
160743
  // only add authorization header if we have a bearer token
160663
160744
  ...state2.getBearerToken() && {
160664
160745
  Authorization: `Bearer ${state2.getBearerToken()}`
@@ -160831,6 +160912,7 @@ function generateGovernanceApi({
160831
160912
  "User-Agent": userAgent,
160832
160913
  "Content-Type": "application/json",
160833
160914
  ...state2.getAuthenticationHeaderOverrides(),
160915
+ ...state2.getConfigurationHeaderOverrides(),
160834
160916
  // only add API version if we have it
160835
160917
  ...resource.apiVersion && { "Accept-API-Version": resource.apiVersion },
160836
160918
  // only add authorization header if we have a bearer token
@@ -161744,7 +161826,7 @@ async function step({
161744
161826
  state2.getHost(),
161745
161827
  getRealmPath(realm2)
161746
161828
  );
161747
- const { data: data2 } = await generateAmApi({
161829
+ const { data: data2 } = await generateAmAuthApi({
161748
161830
  resource: getApiConfig2(),
161749
161831
  state: state2
161750
161832
  }).post(urlString, body2, config4);
@@ -174607,7 +174689,7 @@ var getServerVersionApiConfig = () => ({
174607
174689
  });
174608
174690
  async function getServerInfo({ state: state2 }) {
174609
174691
  const urlString = _util2.default.format(serverInfoUrlTemplate, state2.getHost(), "*");
174610
- const { data: data2 } = await generateAmApi({
174692
+ const { data: data2 } = await generateAmAuthApi({
174611
174693
  resource: getServerInfoApiConfig(),
174612
174694
  requestOverride: {},
174613
174695
  state: state2
@@ -174620,7 +174702,7 @@ async function getServerVersionInfo({ state: state2 }) {
174620
174702
  state2.getHost(),
174621
174703
  "version"
174622
174704
  );
174623
- const { data: data2 } = await generateAmApi({
174705
+ const { data: data2 } = await generateAmAuthApi({
174624
174706
  resource: getServerVersionApiConfig(),
174625
174707
  requestOverride: {},
174626
174708
  state: state2
@@ -174810,6 +174892,7 @@ var SERVICE_ACCOUNT_ALLOWED_SCOPES = [
174810
174892
  s2.CertificateReadScope,
174811
174893
  s2.ContentSecurityPolicyFullScope,
174812
174894
  s2.CustomDomainFullScope,
174895
+ s2.DatasetDeletionFullScope,
174813
174896
  s2.ESVFullScope,
174814
174897
  s2.ESVReadScope,
174815
174898
  s2.ESVRestartScope,
@@ -174822,7 +174905,8 @@ var SERVICE_ACCOUNT_ALLOWED_SCOPES = [
174822
174905
  s2.ProxyConnectFullScope,
174823
174906
  s2.ProxyConnectReadScope,
174824
174907
  s2.ProxyConnectWriteScope,
174825
- s2.CookieDomainsFullScope
174908
+ s2.CookieDomainsFullScope,
174909
+ s2.WSFedAdminScope
174826
174910
  ];
174827
174911
  var SERVICE_ACCOUNT_DEFAULT_SCOPES = [
174828
174912
  s2.AmFullScope,
@@ -174832,13 +174916,15 @@ var SERVICE_ACCOUNT_DEFAULT_SCOPES = [
174832
174916
  s2.ContentSecurityPolicyFullScope,
174833
174917
  s2.CookieDomainsFullScope,
174834
174918
  s2.CustomDomainFullScope,
174919
+ s2.DatasetDeletionFullScope,
174835
174920
  s2.ESVFullScope,
174836
174921
  s2.IdmFullScope,
174837
174922
  s2.IGAFullScope,
174838
174923
  s2.PromotionScope,
174839
174924
  s2.ReleaseFullScope,
174840
174925
  s2.SSOCookieFullScope,
174841
- s2.ProxyConnectFullScope
174926
+ s2.ProxyConnectFullScope,
174927
+ s2.WSFedAdminScope
174842
174928
  ];
174843
174929
  async function isServiceAccountsFeatureAvailable({
174844
174930
  state: state2
@@ -175227,6 +175313,7 @@ Specify a sub-string uniquely identifying a single connection profile host URL.`
175227
175313
  logApiSecret: profiles[0].encodedLogApiSecret ? await dataProtection.decrypt(profiles[0].encodedLogApiSecret) : null,
175228
175314
  authenticationService: profiles[0].authenticationService ? profiles[0].authenticationService : null,
175229
175315
  authenticationHeaderOverrides: profiles[0].authenticationHeaderOverrides ? profiles[0].authenticationHeaderOverrides : {},
175316
+ configurationHeaderOverrides: profiles[0].configurationHeaderOverrides ? profiles[0].configurationHeaderOverrides : {},
175230
175317
  adminClientId: profiles[0].adminClientId ? profiles[0].adminClientId : null,
175231
175318
  adminClientRedirectUri: profiles[0].adminClientRedirectUri ? profiles[0].adminClientRedirectUri : null,
175232
175319
  svcacctName: profiles[0].svcacctName ? profiles[0].svcacctName : null,
@@ -175278,6 +175365,14 @@ async function loadConnectionProfileByHost({
175278
175365
  )
175279
175366
  );
175280
175367
  }
175368
+ if (conn.configurationHeaderOverrides) {
175369
+ state2.setConfigurationHeaderOverrides(
175370
+ mergeDeep(
175371
+ state2.getConfigurationHeaderOverrides(),
175372
+ conn.configurationHeaderOverrides
175373
+ )
175374
+ );
175375
+ }
175281
175376
  state2.setServiceAccountId(conn.svcacctId);
175282
175377
  state2.setServiceAccountJwk(conn.svcacctJwk);
175283
175378
  state2.setServiceAccountScope(conn.svcacctScope);
@@ -175424,6 +175519,19 @@ async function saveConnectionProfile({
175424
175519
  state: state2
175425
175520
  });
175426
175521
  }
175522
+ if (state2.getConfigurationHeaderOverrides() && Object.entries(state2.getConfigurationHeaderOverrides()).length) {
175523
+ profile.configurationHeaderOverrides = state2.getConfigurationHeaderOverrides();
175524
+ printMessage({
175525
+ message: "Advanced setting: Configuration Header Overrides: ",
175526
+ type: "info",
175527
+ state: state2
175528
+ });
175529
+ printMessage({
175530
+ message: state2.getConfigurationHeaderOverrides(),
175531
+ type: "info",
175532
+ state: state2
175533
+ });
175534
+ }
175427
175535
  delete profile.tenant;
175428
175536
  profiles[state2.getHost()] = profile;
175429
175537
  const orderedProfiles = Object.keys(profiles).sort().reduce((obj, key) => {
@@ -175626,7 +175734,7 @@ async function getSessionInfo({
175626
175734
  state2.getHost(),
175627
175735
  getCurrentRealmPath(state2)
175628
175736
  );
175629
- const { data: data2 } = await generateAmApi({
175737
+ const { data: data2 } = await generateAmAuthApi({
175630
175738
  resource: getApiConfig15(),
175631
175739
  state: state2
175632
175740
  }).post(
@@ -176313,7 +176421,8 @@ var CLOUD_ADMIN_DEFAULT_SCOPES = [
176313
176421
  s3.PromotionScope,
176314
176422
  s3.ReleaseFullScope,
176315
176423
  s3.SSOCookieFullScope,
176316
- s3.ProxyConnectFullScope
176424
+ s3.ProxyConnectFullScope,
176425
+ s3.WSFedAdminScope
176317
176426
  ];
176318
176427
  var FORGEOPS_ADMIN_DEFAULT_SCOPES = [s3.IdmFullScope, s3.OpenIdScope];
176319
176428
  var forgeopsAdminScopes = FORGEOPS_ADMIN_DEFAULT_SCOPES.join(" ");
@@ -212460,7 +212569,12 @@ function setup120() {
212460
212569
  ).addOption(
212461
212570
  new Option(
212462
212571
  "--authentication-header-overrides [headers]",
212463
- 'Map of headers: {"host":"am.example.com:8081"}.'
212572
+ 'Map of headers: {"host":"am.example.com:8081"}. These headers are sent with all requests and can be used to override default behavior, for example to set a custom host header for Proxy Connect-protected PingOne Advanced Identity Cloud environments.'
212573
+ )
212574
+ ).addOption(
212575
+ new Option(
212576
+ "--configuration-header-overrides [headers]",
212577
+ 'Map of headers: {"X-Custom-Configuration":"critical"}. These headers are sent with all configuration requests and can be used to override default behavior, for example to set a custom configuration header for mutable PingOne Advanced Identity Cloud environments.'
212464
212578
  )
212465
212579
  ).addOption(
212466
212580
  new Option("--alias [name]", "Alias name for this connection profile.")
@@ -212483,6 +212597,10 @@ function setup120() {
212483
212597
  ` + ` $ frodo conn save --authentication-header-overrides '{"MY-SECRET-HEADER": "proxyconnect secret header value"}' ${amBaseUrl} ${username} '${password}'
212484
212598
  `["brightCyan"] + ` Update an existing connection profile with a custom header override for a freshly Proxy Connect-protected PingOne Advanced Identity Cloud environment:
212485
212599
  ` + ` $ frodo conn save --authentication-header-overrides '{"MY-SECRET-HEADER": "proxyconnect secret header value"}' ${connId}
212600
+ `["brightCyan"] + ` Save a connection profile for a mutable PingOne Advanced Identity Cloud environment:
212601
+ ` + ` $ frodo conn save --configuration-header-overrides '{"X-Configuration-Type": "mutable"}' ${amBaseUrl} ${username} '${password}'
212602
+ `["brightCyan"] + ` Update an existing connection profile with a configuration header override for a freshly mutable PingOne Advanced Identity Cloud environment:
212603
+ ` + ` $ frodo conn save --configuration-header-overrides '{"X-Configuration-Type": "mutable"}' ${connId}
212486
212604
  `["brightCyan"] + ` Update an existing connection profile to use Amster private key credentials with a custom Amster journey (PingAM classic deployments only):
212487
212605
  ` + ` $ frodo conn save --private-key ${amsterPrivateKey} --authentication-service ${customAmsterService} ${classicConnId}
212488
212606
  `["brightCyan"]
@@ -212506,6 +212624,11 @@ function setup120() {
212506
212624
  JSON.parse(options.authenticationHeaderOverrides)
212507
212625
  );
212508
212626
  }
212627
+ if (options.configurationHeaderOverrides) {
212628
+ state.setConfigurationHeaderOverrides(
212629
+ JSON.parse(options.configurationHeaderOverrides)
212630
+ );
212631
+ }
212509
212632
  const needAmsterLogin = !!options.privateKey;
212510
212633
  const needSa = options.sa && !state.getServiceAccountId() && !state.getServiceAccountJwk();
212511
212634
  const needLogApiKey = options.logApi && !state.getLogApiKey() && !state.getLogApiSecret() && needSa;
@@ -226656,7 +226779,7 @@ var compareVersions = (v12, v2) => {
226656
226779
  // package.json
226657
226780
  var package_default2 = {
226658
226781
  name: "@rockcarver/frodo-cli",
226659
- version: "4.0.0-11",
226782
+ version: "4.0.0-12",
226660
226783
  type: "module",
226661
226784
  description: "A command line interface to manage ForgeRock Identity Cloud tenants, ForgeOps deployments, and classic deployments.",
226662
226785
  keywords: [
@@ -226751,7 +226874,7 @@ var package_default2 = {
226751
226874
  ]
226752
226875
  },
226753
226876
  devDependencies: {
226754
- "@rockcarver/frodo-lib": "4.0.0-11",
226877
+ "@rockcarver/frodo-lib": "4.0.0-12",
226755
226878
  "@types/colors": "^1.2.1",
226756
226879
  "@types/fs-extra": "^11.0.1",
226757
226880
  "@types/jest": "^29.2.3",