Compare commits

...
176 Commits
Author SHA1 Message Date
Zhihe Li 7dfaff1538 fix: 🐛 Fix raw api output not displaying codemirror properly (#1354)
✅ Closes: ICU-6249
2022-09-28 14:49:09 -04:00
Zhihe Li e09b4fffe7 chore: 🤖 Update version and changelog for desktop (#1353) 2022-09-27 15:39:39 -04:00
Zhihe Li 3deec2ed50 fix: 🐛 Sort workers when filtering is enabled as well (#1352) 2022-09-27 09:15:42 -04:00
Dharini Jeeva 3fc22b4aa3 fix: 🐛 clear token on normalization (#1351)
* fix: 🐛 clear token on normalization
2022-09-26 18:25:02 -07:00
Cameron PereraandSusmitha Girumala 0cba914045 chore: 🤖 remove unused ssh-target feature flag (#1346)
Co-authored-by: Susmitha Girumala <susmitha@hashicorp.com>
2022-09-26 12:35:25 -05:00
Zhihe LiandCarlos Alcaide Corvo 4c4d4e2351 Fix bug dc token env (#1350)
* Add Boundary password as env variable. WIP

* Add Boundary password as env variable to the spawn process

* fix: 🐛 Fix token flag when connecting a target

Fix a token flag when connecting to a target. Now it uses an env
variable

* Add rest env variables to child processes

Co-authored-by: Carlos Alcaide Corvo <ccorvo@hashicorp.com>
2022-09-26 12:39:49 -04:00
Zhihe Li e2fff61416 fix: 🐛 Add back div to fix tag icon badge layout (#1349) 2022-09-22 17:57:40 -04:00
Zhihe Li 82e531e836 feat: 🎸 Update workers list to be sorted (#1348)
✅ Closes: ICU-6185
2022-09-22 13:24:33 -04:00
Cameron Perera e6d68c2e4a refactor: 💡 fix routing for static credentials from targets (#1347)
* refactor: 💡 fix routing for static credentials from targets

✅ Closes: ICU-6155

* chore: 🤖 Add comment to isStatic credential helper method
2022-09-21 15:10:28 -05:00
Zhihe Li 9e55f5f157 chore: 🤖 Enable BYOW feature (#1345) 2022-09-21 09:30:07 -04:00
Zhihe Li eb539b9c5b Icu 6036 update filter dropdown for tags in list view (#1337)
✅ Closes: ICU-6036
2022-09-20 20:51:06 -04:00
Dharini JeevaandCameron Perera 5224512da0 Icu 6153 unknown credential support (#1344)
* feat: 🎸 Add support for unknown credential types

✅ Closes: ICU-6153

* fix: 🐛 add unknown cred type

* refactor: 💡 move credential type logic to a component

* chore: 🤖 fix component name

* fix: 🐛 update component name, remove unused translated string

* fix: 🐛 file name

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-09-20 19:31:16 -05:00
Zhihe Li 6aec408003 feat: 🎸 Make checkbox equality checks more general (#1335) 2022-09-20 20:13:26 -04:00
Randall Morey f937bbf282 fix: 🐛 stop sending scope_id on cred libraries (#1343) 2022-09-20 18:24:18 -04:00
Zhihe Li 7996d5439c chore: 🤖 Update public worker address wording (#1340) 2022-09-20 17:04:17 -04:00
Dharini Jeeva 3f2a17f59c chore: 🤖 update host catalog ui (#1342)
* chore: 🤖 update host catalog/hosts/host-set azure texts
2022-09-20 13:23:29 -07:00
Dharini Jeeva 24a99d0fb7 chore: 🤖 Host Set Updates (#1333)
host set text updates
2022-09-20 09:51:29 -07:00
Zhihe Li fdc4a13194 Icu 6034 update tags in create page to support multi input fields (#1325)
* feat: 🎸 Change tags to be multi part input fields

✅ Closes: ICU-6034
2022-09-20 10:56:18 -04:00
Devon Anderson 70bfd4c181 feat: 🎸 Update Detail Page to show Tags (#1327)
* feat: 🎸 Update Detail Page to show Tags

Update detailed worker view page to show tags in key:value pair format

✅ Closes: ICU-6037

* refactor: 💡 Fix duplicate yaml variables, and view

Refactor detailed view to have space after comma for value array, and
removed duplicate yaml variables for worker_tags

✅ Closes: ICU-6037

* change title and description translation variables
2022-09-20 09:11:57 -04:00
lisbet-alvarez 10a81f8590 refactor: 💡 translation fix (#1338) 2022-09-19 16:01:14 -07:00
Zhihe Li c75abc11dc feat: 🎸 Add optional icon for dropdown section (#1332) 2022-09-19 16:28:19 -04:00
Dharini Jeeva e17db2e0d6 Update fieldset (#1334)
* chore: 🤖 add helpertext to fieldset and update text
2022-09-19 13:07:31 -07:00
Cameron Perera d2b67fa76c chore: 🤖 enable SSH Targets and Static Credential Store support (#1336) 2022-09-19 09:50:59 -05:00
Cameron Perera 3af439f1e6 refactor: 💡 Update Host Catalog form labels and help text (#1331)
✅ Closes: ICU-6107
2022-09-16 15:14:26 -07:00
Cameron Perera f143ba3d58 refactor: 💡 Update Quick Setup Success screen button route (#1330)
Route to Target details screen now

✅ Closes: ICU-6096
2022-09-16 14:25:45 -05:00
Zhihe Li 82bbe798fd feat: 🎸 update the tags badge in workers list view (#1326)
* feat: 🎸 update the tags badge in workers list view

✅ Closes: ICU-6035
2022-09-16 14:53:29 -04:00
Dharini JeevaandCameron Perera 346e0d356a chore: 🤖 update quicksetup svg (#1329)
Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-09-16 13:02:30 -05:00
Cameron Perera f603c405a7 refactor: 💡 Update Quick Setup resource names (#1328)
* refactor: 💡 Update Quick Setup resource names

✅ Closes: ICU-6094

* refactor: 💡 Fix target quick setup name
2022-09-16 12:17:36 -05:00
Dharini Jeeva 8eeab7e87b Icu 5991 UI add worker filter form field for vault type credential stores (#1318)
* chore: 🤖 add worker_filter to vault cred store
2022-09-14 12:06:34 -07:00
Randall Morey 3d32200cf3 chore: 🤖 disable features (#1317) 2022-09-14 09:49:06 -04:00
Cameron Perera 29d41efade chore: 🤖 Add new flag for vault-worker-filter, ENT/HCP only (#1316)
✅ Closes: ICU-6054
2022-09-13 14:09:10 -07:00
Devon Anderson 8efa3168c8 feat: 🎸 Update worker model (#1313)
* feat: 🎸 Update worker model

Update worker modeel for `release_version` field

✅ Closes: ICU-6044

* refactor: 💡 update mirage factory

Update mirage factory for worker and `release_version`

✅ Closes: ICU-6044

* feat: 🎸 Update detailed worker view (#1315)

Update detailer worker view to include read-only `release_version` field

✅ Closes: ICU-6046

* feat: 🎸 Update workers list-view (#1314)

Update workers list-view to include `release-version`

✅ Closes: ICU-6045
2022-09-13 16:49:48 -04:00
Cameron Perera cd9d3e91e5 refactor: 💡 Add worker_filter to vault credential stores (#1310)
* refactor: 💡 Add worker_filter to vault credential stores

Add worker_filter attribute to vault type credential store model

✅ Closes: ICU-5988

* refactor: 💡 Add worker_filter mirage mock for credential store (#1312)

✅ Closes: ICU-5990
2022-09-13 15:23:28 -05:00
Devon AndersonandZhihe Li 3c49dc1c48 feat: 🎸 Feature flag for oss and hcp binary (#1305)
* feat: 🎸 Feature flag for `oss` and `hcp` binary

Create feature flag for `oss` and `hcp` to change specific input fields
based on binary editions

✅ Closes: ICU

* Update ui/admin/app/components/form/worker/create-worker-led/index.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* Update ui/admin/app/components/form/worker/create-worker-led/index.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* refactor: 💡 Quick refactor

Refactor `create-worker-led/index.js`, and test.

✅ Closes: ICU-5903

* refactor: 💡 refactor for better readability

Refactor code for better readability

* refactor: 💡 rename filter function

rename array filter function to be more descriptive

✅ Closes: ICU-5903

* changed params name for  `convertCommaSeparatedValuesToArray`

* add ending new line

* Update ui/admin/app/components/form/worker/create-worker-led/index.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* refactor: 💡 yaml refactor

yaml refactor

* refactor: 💡 revert en-us.yaml file

revert en-us.yaml file

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2022-09-12 16:04:29 -04:00
Zhihe Li e6767b1e14 Chore/enable yaml formatting (#1307) 2022-09-12 15:17:21 -04:00
Carlos Alcaide Corvo 3347668b41 chore: 🤖 Add feature flags for dev and test environments (#1306) 2022-09-12 15:58:08 +02:00
Zhihe Li 34da192ef9 chore: 🤖 Enable stylistic linting rules (#1298) 2022-09-07 16:21:27 -04:00
Dharini Jeeva d930c3da3a chore: 🤖 enable ssh-target for production (#1302)
* chore: 🤖 enable ssh-target for production
2022-09-07 09:48:29 -07:00
lisbet-alvarez 0a2305bba9 feat: 🎸 Enable Static Credentials flag for Production (#1301)
✅ Closes: ICU-5952
2022-09-06 13:23:02 -07:00
Zhihe Li 86ab7331af fix: 🐛 Fix tag bug from moving where workers list is loaded (#1284)
* fix: 🐛 Fix tag bug from moving where workers list is loaded

* style: 💄 Remove unused import

* refactor: 💡 Use new setting to turn off auto refresh for filter
2022-09-06 13:45:22 -04:00
Dharini Jeeva c351452d71 test: 💍 acceptance tests for injected credentials (#1297)
test: 💍 acceptance tests for injected application credentials
2022-09-02 13:10:27 -07:00
Dharini Jeeva 8952541203 Add injected credentials tab (#1295)
* chore: 🤖 introduce injected application credentials on the UI
2022-09-02 12:29:39 -07:00
Devon Anderson 128b0ff492 refactor: 💡 Add tab navigation to detailed worker view page (#1288)
Added tab navigation to detailed worker view page.

✅ Closes: ICU-5901
2022-09-02 10:48:23 -04:00
Zhihe Li ccf462019b chore: 🤖 Add eol-last rule (#1296)
* chore: 🤖 Add eol-last rule

* style: 💄 Add newlines for core

* style: 💄 Add newlines to EOF in rose

* style: 💄 Add newlines for admin

* style: 💄 Add newlines in desktop templates
2022-09-01 17:43:30 -04:00
Zhihe Li a69d01c9fc Chore/enable quote rule (#1294)
* chore: 🤖 Add quote rule to use single quotes in templates
2022-09-01 16:39:56 -04:00
Randall MoreyandSusmitha Girumala a2e27b09c3 refactor: 💡 add standalone server mocks to auth tests (#1283)
* refactor: 💡 replace ember notify with flash in notify decorator

* refactor: 💡 remove embery-notify and replace last instance

* chore: 🤖 upgrade ember dependencies in anticipation of ember 4

* refactor: 💡 add standalone server mocks to auth tests

Co-authored-by: Susmitha Girumala <susmitha@hashicorp.com>
2022-09-01 15:40:00 -04:00
Randall Morey 3ff89279e6 chore: 🤖 add refreshRouteOnChange option to resource filters (#1289) 2022-09-01 13:27:34 -04:00
Dharini Jeeva 2614b311a1 Icu 5578 - introduce injected application credential on the api (#1269)
* chore: 🤖 include injected cred sources to the target model
2022-09-01 10:07:36 -07:00
Cameron Perera bd0854b0f6 refactor: 💡 update password input field to be a password type (#1291) 2022-08-31 17:26:47 -05:00
Cameron Perera e019b825ac refactor: 💡 update passphrase field to a password text input (#1292)
Update passphrase field to a text input to allow for adding a password
type
2022-08-31 17:08:34 -05:00
Zhihe Li 6fd0301635 chore: 🤖 Remove "ember-template-lint-plugin-prettier" (#1293)
* chore: 🤖 Remove "ember-template-lint-plugin-prettier"
2022-08-31 17:17:14 -04:00
Randall Morey 96cf75bfdb chore: 🤖 upgrade ember dependencies in anticipation of ember 4 (#1280)
* refactor: 💡 replace ember notify with flash in notify decorator

* refactor: 💡 remove embery-notify and replace last instance

* chore: 🤖 upgrade ember dependencies in anticipation of ember 4
2022-08-31 11:41:50 -07:00
Randall Morey 4a6ed0b509 refactor: 💡 replace ember notify with flash in notify decorator (#1272)
* refactor: 💡 replace ember notify with flash in notify decorator

* refactor: 💡 remove embery-notify and replace last instance
2022-08-31 10:24:25 -07:00
Randall MoreyandZhihe Li cde6abd445 refactor: 💡 convert brokered cred IDs array to simple attribute (#1259)
* refactor: 💡 convert brokered cred IDs array to simple attribute

* fix: 🐛 missing test assertion

* fix: 🐛 simplify computed

* refactor: 💡 convert host sources array to simple attribute (#1260)

* refactor: 💡 convert host source IDs array to simple attribute

* fix: 🐛 host source tests

* Refactor role fragment arrays (#1262)

* refactor: 💡 convert grant strings to regular attribute

* refactor: 💡 convert principals array to simple attribute

* Update ui/admin/app/routes/scopes/scope/roles/role.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* fix: 🐛 remove unused import

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2022-08-31 09:55:59 -07:00
Cameron Perera 83c7b76f48 refactor: 💡 Update passphrase to private_key_passphrase (#1290)
✅ Closes: ICU-5916
2022-08-30 20:40:31 -05:00
lisbet-alvarezandZhihe Li cb3104a624 test: 💍 Add acceptance tests for deleting an spk credential (#1274)
✅ Closes: ICU-5654

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2022-08-30 13:01:38 -07:00
lisbet-alvarez f1f7be4067 test: 💍 clean-up acceptance test for list-view of credentials (#1278)
✅ Closes: ICU-5650
2022-08-30 12:44:17 -07:00
lisbet-alvarez 0ae2451b9c test: 💍 Add acceptance test for updating an spk credential (#1273)
* test: 💍 Add acceptance test for updating an spk credential

✅ Closes: ICU-5652
2022-08-30 12:20:52 -07:00
Dharini Jeeva 069a864cbb chore: 🤖 add abilities for injected app cred sources (#1285)
* chore: 🤖 add abilities for injected app cred sources
2022-08-30 12:01:59 -07:00
Dharini Jeeva a3337b3771 Add injected application credential support (#1282)
* fix: 🐛 credential application injection translations
2022-08-30 10:52:21 -07:00
Dharini Jeeva 9ee89585ec Remove unused console logs (#1286)
* fix: 🐛 remove unused logs
2022-08-30 09:49:34 -07:00
Devon Anderson 03b603be54 refactor: 💡 Disable read-only fields when editing worker (#1287)
Refactor detailed worker to not hide read-only fields when editing, but
leave them disabled

✅ Closes: ICU-5902
2022-08-30 12:11:19 -04:00
bc7ed3f0ed ICU 5247 detailed worker view and ICU 5248 edit worker view (#1246)
* feat: 🎸 Add list view for workers

✅ Closes: ICU-5251

* feat: 🎸 Add route for worker detail and include links in table

* refactor: 💡 Updated id display in table and fixed worker route

* test: 💍 Add workers list test

* feat: 🎸 Add worker detailed view and edit view

Added worker detailed view and editable form view for name and
description of worker

✅ Closes: ICU-5247 ICU-5248

* refactor: 💡 fixed conflict merge

fixed merge conflicts for scope/workers/worker

✅ Closes: ICU-5247

* Update ui/admin/app/routes/scopes/scope/workers.js

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>

* Update ui/admin/app/templates/scopes/scope/workers/worker/index.hbs

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>

* test: 💍 Test for worker/update-test.js

Created update-test.js and refactored worker/form.hbs for correct
display of last_seen

✅ Closes: ICU-5247

* Update ui/admin/app/routes/scopes/scope/workers.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* Update ui/admin/app/templates/scopes/scope/workers/worker/index.hbs

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* Update ui/admin/tests/acceptance/workers/read-test.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* refactor: 💡 code refactor and test creation

Refactored code for detailed worker view, created controller for
detailew worker view to display worker name in breadcrumbs, added test
for `delete`, `update`.

✅ Closes: ICU-5247

* refactor: 💡 Refactor test

Refactor update-test.js and clean up code.

✅ Closes: ICU-5247

* refactor: 💡 fixed workers/update-test.js

added local variable for better test coverage for cancel test in
workers/update-test.js

✅ Closes: ICU-5247

* refactor: 💡 fix test

Refactored yaml file for `last_seen.description`

✅ Closes: ICU-5247

* Update ui/admin/app/routes/scopes/scope/workers.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* removed `type` from  `<form.textarea/>` component

* Update ui/admin/app/controllers/scopes/scope/workers/worker.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* spacing for linter

* refactor: 💡 Refactor test

Refactored `worker/read-test.js` to to test correct authorization

✅ Closes: ICU-5247

* ci: 🎡 Fixed lint

fixed lint

✅ Closes: ICU-5247

* refactor: 💡 Added custom relatvie date to field

Added custom relative date to `last_status_time` input for worker view.

✅ Closes: ICU-5247

* refactor: 💡 refactored yaml file

changed delete dropdown for worker to `actions.delete`

✅ Closes: ICU-5247

* Removed unused services from workers.js

* merge changes from main

* fix lint

* fix lint

* Update index.hbs

lint issues

* refactor: 💡 fixed lint for hbs

fixed linting issues for hbs files

✅ Closes: ICU-5247 ICU-5249

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
2022-08-29 10:24:41 -04:00
lisbet-alvarezandZhihe Li 0dff900795 test: 💍 Add acceptance tests for reading an spk credential (#1275)
Acceptance tests for spk type credentials added to read-test.js

✅ Closes: ICU-5653

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2022-08-26 09:54:10 -07:00
Devon AndersonandZhihe Li a3517e53a8 chore: 🤖 create relative date helper (#1276)
* chore: 🤖 create relative date helper

Create a relative date helper that outputs "time" ago format.

✅ Closes: ICU-5847

* Update addons/core/addon/helpers/relative-datetime-live.js

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>

* refactor: 💡 refactor test for relative-date-helper

refactor test for relative-datetime-live helper

✅ Closes: ICU-5847

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2022-08-26 12:22:24 -04:00
Zhihe Li 3130831ae0 feat: 🎸 Add create worker page (#1244)
* feat: 🎸 Add create worker page

✅ Closes: ICU-5246
2022-08-26 11:50:53 -04:00
Zhihe Li dd0d37241c feat: 🎸 Add code editor to api response display (#1271)
✅ Closes: ICU-5767
2022-08-26 11:01:23 -04:00
Cameron Perera 9a10b68bbe refactor: 💡 update credential serializer to delete password (#1277)
* refactor: 💡 update credential serializer to delete password

update credential serializer to delete password attribute if empty
string or null allowing the user to update just the username if needed.

✅ Closes: ICU-5731

* refactor: 💡 update serializer comments and test names
2022-08-25 17:02:48 -05:00
Zhihe Li 30b9f65251 chore: 🤖 Update electron to v16 (#1267)
✅ Closes: ICU-4018
2022-08-25 12:04:59 -04:00
fb981c02ea Icu 5651 create spk type (#1266)
Add functionality for creating a ssh private key credential and add
corresponding acceptance tests.

✅ Closes: ICU-5651

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
Co-authored-by: Randall Morey <randall@randallmorey.com>
Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2022-08-24 15:50:48 -07:00
Zhihe Li 1ee83dd1e6 chore: 🤖 Cleanup rose (#1270)
* refactor: 💡 Clean up use of classnames in rose

* fix: 🐛 Fix form action story using wrong disabled field
2022-08-22 16:17:06 -04:00
Dharini Jeeva 359614517e fix: 🐛 add translation string (#1268) 2022-08-18 15:50:53 -07:00
Dharini Jeeva 9a8665a314 Refactor credential sources to brokered credential sources (#1264)
* chore: 🤖 refactor credential sources to brokered credential source
2022-08-18 09:11:38 -07:00
Dharini Jeeva f4f7c0e343 fix: 🐛 disable scope (#1265) 2022-08-18 08:23:43 -07:00
lisbet-alvarezandCameron Perera dae5174d2f feat: 🎸 Update the credentials route to support both types (#1263)
Add query param to the credential route in order to support the new ssh
private key type

✅ Closes: ICU-5649

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-08-17 14:48:52 -07:00
Cameron Perera 53eef5caeb feat: 🎸 Add SSH Private Key mirage support (#1261)
* feat: 🎸 Add SSH Private Key mirage support

Update mirage to mock SSH Private key credential types

✅ Closes: ICU-5647

* refactor: 💡 remove default case in credential mirage mock
2022-08-17 13:20:21 -05:00
Cameron Perera 50038cdf85 Icu 5646 serializer (#1257)
* feat: 🎸 Update Credential Serializer

Add support for SSH Private Key credentials

✅ Closes: ICU-5646

* test: 💍 Add normalize test for ssh private key credentials

* refactor: 💡 remove deletion of hmac attributes in serializer
2022-08-16 14:35:33 -05:00
Randall Morey 7386b2c9ed refactor: 💡 deauth should delete the auth token (#1256) 2022-08-15 11:22:27 -07:00
Dharini Jeeva e3324ad64a chore: 🤖 rename application_credentials_sources_ids to brokered (#1255) 2022-08-15 09:48:12 -07:00
Cameron Perera 39c0835a99 feat: 🎸 Update credential model with ssh private key attributes (#1254)
✅ Closes: ICU-5645
2022-08-12 15:56:19 -05:00
lisbet-alvarez 29e3e8b843 feat: 🎸 Enable SSH Targets for development (#1239)
Enable SSH Targets for development ENV. Already enabled for testing ENV.

✅ Closes: ICU-5553
2022-08-12 10:33:05 -07:00
lisbet-alvarez 72b7b85ad1 chore: 🤖 remove filter feature flag (#1252)
✅ Closes: ICU-5599
2022-08-12 10:02:05 -07:00
Dharini Jeeva 9a1d1225ca chore: 🤖 remove unused oidc-account-crud feature flag (#1249) 2022-08-12 09:43:19 -07:00
Dharini Jeeva 33728a6496 chore: 🤖 remove managed_groups feature flag (#1253) 2022-08-12 09:27:02 -07:00
lisbet-alvarez bf2a6aeb6a chore: 🤖 remove oidc-crud feature flag (#1248)
* chore: 🤖 remove oidc-crud feature flag

✅ Closes: ICU-5597

* Update environment.js to resolve confilicts
2022-08-11 16:01:47 -07:00
Dharini Jeeva 746426fc82 chore: 🤖 cleanup feature flags - OIDC (#1245)
* chore: 🤖 cleanup OIDC feature flag
2022-08-11 15:37:44 -07:00
Randall Morey d8b5056094 fix: 🐛 fixes host set attributes field types (#1251) 2022-08-11 16:10:42 -04:00
lisbet-alvarez bdc2238f17 chore: 🤖 add got package to resolutions (#1243) 2022-08-11 12:41:34 -07:00
Zhihe Li 1842631056 fix: 🐛 Add feature flag for BYOW (#1250) 2022-08-11 13:47:22 -04:00
lisbet-alvarez 6f2a04d4c6 chore: 🤖 add async to resolutions (#1242) 2022-08-10 12:28:55 -07:00
Randall Morey e0b59b7d8b fix: 🐛 icu-5258 filter field is not sent in payload (#1238) 2022-08-10 11:58:12 -07:00
lisbet-alvarez fbf6b2c201 chore: 🤖 chore(deps): upgrade got package version (#1241)
add got to resolutions
2022-08-10 10:41:39 -07:00
lisbet-alvarez 7b212efcf2 chore: 🤖 Add terser to resolutions (#1237)
* chore: 🤖 bump terser from 4.8.0 to 4.8.1

* chore: 🤖 Update all terser dependency instances to 5.14.2
2022-08-10 10:15:13 -07:00
Dharini Jeeva ecb34d7427 chore: 🤖 dependency update (#1240) 2022-08-10 09:46:48 -07:00
Zhihe Li 4ab7304411 feat: 🎸 Added list view for workers (#1234)
* feat: 🎸 Add list view for workers

✅ Closes: ICU-5251
2022-08-09 16:12:56 -04:00
Devon AndersonandDharini Jeeva 62077d3c25 feat: 🎸 Add worker serializer (#1230)
* feat: 🎸 Add worker serializer

Add worker serializer that focus' on `config_tags.type` and
`canonical_tags.type`.
[API](https://docs.google.com/document/d/1G-lfl8gk9NfoKFImSpHb90E3xC3CSEVDwVy3bJ9eOhA/edit#heading=h.9e06o4b8etpi)

✅ Closes: ICU-5241

* refactor: 💡 refactored `models/worker.js`

Because `canonical_tags` and `config_tags` are `readOnly` attributes, we
could use `attr` decorator instead of `fragment`.

✅ Closes: ICU-5241

* refactored `model/worker.js and deleted un-needed files

* refactor: 💡 Refactored model/worker.js and created test

Refactored model/worker.js to include custom method for POST route for
adding new worker.

BREAKING CHANGE: 🧨 no

✅ Closes: ICU-5241

* refactor: 💡 Refactored custom POST route method for worker

Refactored custom method on `model/worker.js` to include serialization
for `worker_genrated_auth_token`

BREAKING CHANGE: 🧨 no

✅ Closes: ICU-5241

* refactor: 💡 Refactor test

Refactor model/worker-test.js and serializers/worker.js

BREAKING CHANGE: 🧨 no

✅ Closes: ICU-5241

* Update addons/api/addon/serializers/worker.js

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>

* update worker.js documentation block

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
2022-08-09 15:34:42 -04:00
Dharini Jeeva 1f0baceb5e Icu 5476 refactor target model serializer and mirage (#1235)
chore: 🤖 refactor target model to support credentials
2022-08-08 09:21:07 -07:00
Cameron Perera 2cda4f639e refactor: 💡 update onSubmit for add-credential-sources (#1233)
Remove submit action from form component and pass selected credential
IDs directly to the submit method
2022-08-04 14:53:44 -05:00
Cameron Perera 9f09f01f36 Icu 5253 add query to include credentials (#1227)
* refactor: 💡 add-credential-sources to include credentials

* refactor: 💡 update add-credential-sources template

Update to how AddCredentialSources form is rendered in the template

✅ Closes: ICU-5253

* refactor: 💡 Update add-credential-sources method signatures

* refactor: 💡 change how add-credential-source form is rendered

* refactor: 💡 Remove duplicate add-credential-sources message

Remove the duplicate No Credential Credential Sources message from
add-credential-sources form

* refactor: 💡 Move filter logic to controller

Move credential source filter logic from route to controller for
add-credential-sources

* test: 💍 Verify all available credential sources are listed
2022-08-02 11:55:26 -05:00
dependabot[bot]andRandall Morey c8a76078ec chore(deps): bump json-pointer from 0.6.1 to 0.6.2 (#1224)
Bumps [json-pointer](https://github.com/manuelstofer/json-pointer) from 0.6.1 to 0.6.2.
- [Release notes](https://github.com/manuelstofer/json-pointer/releases)
- [Commits](https://github.com/manuelstofer/json-pointer/commits)

---
updated-dependencies:
- dependency-name: json-pointer
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-08-01 14:35:23 -07:00
Zhihe Li 96b0ae3b06 Icu 5245 add workers tab to navigation and initial overview (#1229)
* feat: 🎸 Add initial workers UI navigation page

✅ Closes: ICU-5245
2022-08-01 16:04:41 -04:00
Cameron Perera bc6f849270 fix: 🐛 Fix routing issue for new credential stores (#1232) 2022-08-01 14:41:24 -05:00
Carlos Alcaide Corvo 2fcfab7c1c refactor: 💡 Deprecate faker to use @faker-js (#1223) 2022-08-01 14:25:07 -04:00
lisbet-alvarez 210296f298 refactor: 💡 Remove helper text for Username & Password (#1231)
Remove helper text for username and password fields in Credential form
as requested in a previous conversation.

✅ Closes: ICU-5459
2022-08-01 10:47:36 -07:00
Randall Morey c675f790ef fix: 🐛 change password route should not error (#1228) 2022-07-29 15:18:57 -07:00
Zhihe Li b722fa361b * feat: 🎸 Add code-editor component (#1207)
* feat: 🎸 Add code-editor component

Added code editor component which was taken from HCP, tweaked styles and
imports to use boundary assets

✅ Closes: ICU-5167
2022-07-29 17:18:07 -04:00
Randall Morey 40184006cd chore: 🤖 introduce hcp edition for naming consistency (#1225) 2022-07-29 10:10:40 -07:00
Randall Morey ec56d2fbbe fix: 🐛 role discard should not error (#1226) 2022-07-28 17:49:51 -07:00
Randall Morey bfc433dc38 feat: 🎸 add scope filtering to role/add-principals route (#1211)
* feat: 🎸 add scope filtering to role/add-principals route

* fix: 🐛 remove unnecessary helper

* feat: 🎸 add scope filtering to group add-members route
2022-07-28 17:34:03 -07:00
lisbet-alvarez f6e1fb0e3b Icu 5330 credentials crudl tests (#1219)
* test: 💍 Add credentials CRUDL tests

* fix: 🐛 Deleted empty files

* test: 💍 Add missing tests for credentials

* test: 💍 Revise tests in read-test.js

✅ Closes: ICU-5330
2022-07-28 15:34:03 -07:00
Zhihe Li 2b58e82d6d feat: 🎸 Add worker mirage mocks (#1217)
✅ Closes: ICU-5240
2022-07-28 14:57:53 -04:00
Zhihe Li a84e8c693e feat: 🎸 Add worker model (#1213)
✅ Closes: ICU-5239
2022-07-28 14:33:23 -04:00
Michele Degges dcf24478bd [CI-only] Add build job for HCPb variant (#1221)
This new job mirrors the enterprise build job, but lets us keep the existing logic laid out in https://github.com/hashicorp/boundary/blob/main/.github/workflows/build.yml#L136 to download the right UI artifacts based on the boundary variant/edition.
2022-07-28 08:39:01 -07:00
Carlos Alcaide Corvo 04d14005c0 Fix runtime-settings to not access directly the private variable (#1220) 2022-07-27 11:14:59 -07:00
Carlos Alcaide Corvo 4fcb005a1f Refactor origin to cluster (#1210) 2022-07-27 10:25:01 -07:00
lisbet-alvarez 40ba4286d3 refactor: 💡 Edit a credentail (#1218)
Password input field is now only viewable after user clicks on "Edit
Form"

✅ Closes: ICU-5180
2022-07-27 09:20:03 -07:00
Dharini Jeeva 409e68de1e chore: 🤖 add delete and patch mirage request for credential (#1216) 2022-07-26 13:35:04 -07:00
Cameron Perera 32ba330889 fix: 🐛 spelling error in getting started on desktop redirect (#1215) 2022-07-26 13:39:39 -05:00
lisbet-alvarez f00da3d8d7 test: 💍 credential store CRUDL tests (#1212)
Revised acceptance tests to reflect two types of credential stores

✅ Closes: ICU-5329

* test: 💍 credential store CRUDL tests

* test: 💍 small addition to type of cred. store

* test: 💍 Add missing vault cred. store type tests

* fix: 🐛 rename variable in read-test.js
2022-07-26 10:02:29 -07:00
Cameron Perera f51c56b4a1 feat: 🎸 Add doc link to Credential screens (#1214)
✅ Closes: ICU-5317
2022-07-26 11:04:01 -05:00
Cameron Perera d996d085a1 Icu 5335 add doc link for credential store screens (#1208)
* feat: 🎸 Add doc links to Credential Store screens

✅ Closes: ICU-5335

* test: 💍 Add tests for Credential Store doc links
2022-07-25 12:03:21 -05:00
9274849622 feat: 🎸 display credentials for static credential store (#1205)
* feat: 🎸 Create Credential Model in API

✅ Closes: ICU-5229

* feat: 🎸 update credential model

Add attributes to credential model

✅ Closes: ICU-5229

* feat: 🎸 no verify

✅ Closes: ICU-5230

* feat: 🎸 Add credential serializer and tests

✅ Closes: ICU-5230

* feat: 🎸 Add credential serializer

Credential serializer along with unit tests were added.

✅ Closes: ICU-5230

* feat: 🎸 Credential serializer & unit tests

✅ Closes: ICU-5230

* chore: 🤖 lint

* chore: 🤖 lint

* chore: 🤖 lint

* feat: 🎸 display credentials for static credential store

* chore: 🤖 update translated string

* feat: 🎸 create a credential

* fix: 🐛 add dropdown link for create new credential

* Update new.js

* Update credentials.js

* chore: 🤖 remove the commented block

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
Co-authored-by: Lisbet Alvarez <lisbet.alvarez@hashicorp.com>
Co-authored-by: lisbet-alvarez <107949262+lisbet-alvarez@users.noreply.github.com>
2022-07-25 11:42:34 -05:00
Cameron Perera ae0ce2bfad fix: 🐛 Add missing mirage config urls for credentials (#1209) 2022-07-22 12:29:53 -05:00
lisbet-alvarezandCameron Perera 27a676774c Icu 5232 credential mirage mocks (#1204)
* feat: 🎸 Add mirage mocks for credential

✅ Closes: ICU-5232

* chore: 🤖 Update Credential Store factory to handle credentials

✅ Closes: ICU-5232

* feat: 🎸 Added mirage mocks for credential

✅ Closes: ICU-5232

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-07-21 13:48:16 -07:00
Randall MoreyandDharini Jeeva 379609217b fix: 🐛 roles and principals on projects should be visible (#1202)
* fix: 🐛 roles and principals on projects should be visible

* Update ui/admin/app/routes/scopes/scope/roles/role/index.js

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
2022-07-21 13:09:03 -07:00
Dharini Jeeva b31a513ec1 Create static credentials tab (#1203)
Create static credentials tab  (#1203)
2022-07-21 10:03:13 -07:00
lisbet-alvarezandCameron Perera 821b9b56a7 Icu 5230 credential serializer (#1200)
* feat: 🎸 Create Credential Model in API

✅ Closes: ICU-5229

* feat: 🎸 update credential model

Add attributes to credential model

✅ Closes: ICU-5229

* feat: 🎸 no verify

✅ Closes: ICU-5230

* feat: 🎸 Add credential serializer and tests

✅ Closes: ICU-5230

* feat: 🎸 Add credential serializer

Credential serializer along with unit tests were added.

✅ Closes: ICU-5230

* feat: 🎸 Credential serializer & unit tests

✅ Closes: ICU-5230

* fix: 🐛 Resolved commit conflicts

✅ Closes: ICU-5230

* fix: 🐛 deleted password_hmac from inside the serializer

✅ Closes: ICU-5230

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-07-20 12:34:18 -07:00
Randall Morey c1e1b42672 Feature cross scope role principals (#1199)
* chore: 🤖 add scope column to role principals and group members

* chore: 🤖 add recursion and filtering to user and group mocks

* feat: 🎸 expose groups and roles on projects

* feat: 🎸 enable cross-scope assignment of group members

* chore: 🤖 query group members in a single call via filtering

* chore: 🤖 query role prinicipals in two calls via filtering

* chore: 🤖 use const instead of let

* feat: 🎸 support adding cross-scope principals to roles
2022-07-19 15:18:30 -07:00
lisbet-alvarezandCameron Perera bd0189cf10 Icu 5229 credential model (#1197)
* feat: 🎸 Create Credential Model in API

✅ Closes: ICU-5229

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-07-19 13:02:04 -07:00
Randall Morey ca1b2ce278 Chore optimize iam queries (#1198)
* chore: 🤖 add scope column to role principals and group members

* chore: 🤖 add recursion and filtering to user and group mocks

* feat: 🎸 expose groups and roles on projects

* feat: 🎸 enable cross-scope assignment of group members

* chore: 🤖 query group members in a single call via filtering

* chore: 🤖 query role prinicipals in two calls via filtering

* chore: 🤖 use const instead of let
2022-07-19 12:11:16 -07:00
Dharini Jeeva bc76d49729 create static credential store form and route updates (#1195)
* chore: 🤖 static cred store support to route and templates
2022-07-19 09:29:43 -07:00
Randall Morey 94530cec9c Feature cross scope group members (#1196)
* chore: 🤖 add scope column to role principals and group members

* chore: 🤖 add recursion and filtering to user and group mocks

* feat: 🎸 expose groups and roles on projects

* feat: 🎸 enable cross-scope assignment of group members
2022-07-18 16:36:43 -07:00
Randall Morey 31cf696902 Feature expose roles groups in projects - ICU-4512 (#1192)
* chore: 🤖 add scope column to role principals and group members

* chore: 🤖 add recursion and filtering to user and group mocks

* feat: 🎸 expose groups and roles on projects
2022-07-18 16:15:51 -07:00
Randall Morey c2083aefab chore: 🤖 add recursion and filtering to user and group mocks - ICU-4528 (#1190)
* chore: 🤖 add scope column to role principals and group members

* chore: 🤖 add recursion and filtering to user and group mocks
2022-07-18 15:53:34 -07:00
Randall MoreyandCarlos Alcaide Corvo 817d2a44e1 chore: 🤖 add scope column to role principals and group members (#1184)
Co-authored-by: Carlos Alcaide Corvo <ccorvo@hashicorp.com>
2022-07-18 14:26:26 -07:00
Randall Morey bdabcc119e Refactor base scope fragment (#1166)
* refactor: 💡 migrate managed-group off fragments

* refactor: 💡 migrate credential-store off fragments

* refactor: 💡 migrate credential-library off fragments

* refactor: 💡 migrate account off fragments

* refactor: 💡 convert base model scope field to simple attr

* fix: 🐛 skip broken test
2022-07-18 11:30:53 -07:00
Dharini Jeeva b6a811cbbd fix: 🐛 filter out scopes with no auth methods (#1115)
* fix: 🐛 filter out scopes with no authenticatable auth methods
2022-07-18 09:08:09 -07:00
Dharini Jeeva 6c3e5ba4a8 chore: 🤖 add static credential store support (#1191)
* chore: 🤖 add static credential store support to the API layer
2022-07-15 13:24:04 -07:00
lisbet-alvarez b18f21e6f9 feat: 🎸 Read a credential store (#1193)
This change includes making static type credential stores clickable when
listing all credential stores, along with view the individual credential
store.

✅ Closes: ICU-5173
2022-07-15 12:39:45 -07:00
lisbet-alvarezandCameron Perera ed7e24b328 refactor: 💡 existing vault form field to radio group (#1189)
Refactored existing vault form field to use radio card instead. This
change is seen on details tab of a static credential store.

✅ Closes: ICU-5171

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
2022-07-14 15:53:12 -07:00
Carlos Alcaide Corvo 66d115ab06 fix: 🐛 Add Hawk to resolutions (#1186) 2022-07-14 10:29:25 -07:00
Cameron Perera 9ad8eb93c7 refactor: 💡 Remove credential-store feature flag references (#1188) 2022-07-14 09:42:09 -05:00
lisbet-alvarez 970101d5dc feat: 🎸 Added the static-credentials feature flag (#1187)
The static-credentials feature flag was added and set to true only for
dev and test modes.

✅ Closes: ICU-5203
2022-07-13 14:11:02 -07:00
Cameron PereraandDharini Jeeva 985566d8eb docs: ✏️ Create README for translations (#1182)
✅ Closes: ICU-3872

Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
2022-07-13 11:17:13 -05:00
Carlos Alcaide Corvo 7234a3841a fix: 🐛 Add shell-quote to resolutions (#1185) 2022-07-12 14:55:31 -07:00
Dharini Jeeva 28c9e600aa Update content security (#1173)
* chore: 🤖 upgrade ember content security policy
2022-07-12 10:12:06 -07:00
Carlos Alcaide Corvo 163bbc9fb8 refactor: 💡 Refactor default values for target creation (#1180) 2022-07-12 08:36:35 -07:00
Carlos Alcaide Corvo b54e68cb86 chore: 🤖 Update ember-auto-import (#1178) 2022-07-12 08:09:49 -07:00
78585d999b feat: 🎸 switch to new token type parameter (#1082)
Boundary is deprecating the use of the token_type
parameter to the Authenticate endpoint, instead
replacing it with the new type parameter.

See https://github.com/hashicorp/boundary/commit/80b2c9230fa84605d9aaf7c862f780b50690a36e
for more context.

Co-authored-by: Randall Morey <randall@randallmorey.com>
Co-authored-by: Carlos Alcaide Corvo <ccorvo@hashicorp.com>
2022-07-11 16:39:20 -07:00
Carlos Alcaide Corvo ef9513fea9 fix: 🐛 Fix lock file discrepancy (#1183) 2022-07-11 14:47:04 -07:00
Dharini Jeeva 92fdacb635 test: 💍 onboarding tests (#1181) 2022-07-11 10:47:26 -07:00
Carlos Alcaide Corvo d16c50e33f chore: 🤖 Update ember-cli (#1176) 2022-07-11 09:49:50 -07:00
Zhihe Li 22e8971a5b chore: 🤖 Update git hook to not use commitizen on merges (#1177) 2022-07-07 15:58:39 -04:00
Carlos Alcaide Corvo f5c183a0bd chore: 🤖 Update Sinon to v14 (#1175) 2022-07-07 11:59:31 -07:00
Carlos Alcaide Corvo 49303469cb fix: 🐛 Fix ember-electron incorrect per dep (#1174) 2022-07-07 11:38:43 -07:00
Carlos Alcaide Corvo 6f8afbb7af Chore update eslint and plugins update (#1171) 2022-07-07 11:18:51 -07:00
Carlos Alcaide Corvo 923526ad26 chore: 🤖 Update electron to v15 (#1172) 2022-07-07 11:03:50 -07:00
Dharini Jeeva c21b8fdb64 chore: 🤖 update changelog (#1170)
* chore: 🤖 update changelog and bump up the binary version to 0.9.1
2022-07-06 13:13:57 -07:00
Carlos Alcaide CorvoandRandall Morey 60005f0233 chore: 🤖 Update @babel/plugin-proposal-decorators (#1157)
Update @babel/plugin-proposal-decorators

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-30 08:52:07 -04:00
Randall Morey da89e2f82e fix: 🐛 unable to filter for terminated sessions (#1169)
* fix: 🐛 unable to filter for terminated sessions

* fix: 🐛 reenable sessions mocks
2022-06-29 20:42:12 -04:00
Carlos Alcaide CorvoandRandall Morey c9d6f37343 chore: 🤖 Update @ember/test-helpers (#1159)
Update @ember/test-helpers

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 17:35:17 -04:00
Carlos Alcaide CorvoandRandall Morey 85e4b46821 Chore update doctoc (#1165)
* chore: 🤖 Update doc toc

Update doc toc

* chore: 🤖 Fix doctoc within core

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 16:26:36 -04:00
Carlos Alcaide CorvoandRandall Morey d464419e47 chore: 🤖 Update Cross OS (#1164)
Update Cross OS

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 15:28:46 -04:00
Carlos Alcaide CorvoandRandall Morey 021803942f chore: 🤖 Update babel-loader (#1163)
Update babel-loader

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 15:10:41 -04:00
Randall Morey eeba8dceb6 fix: 🐛 merge conflict in yarn.lock (#1168) 2022-06-29 14:10:59 -04:00
Carlos Alcaide CorvoandRandall Morey 8764633111 chore: 🤖 Update @hashicorp/flight-icons (#1162)
Update @hashicorp/flight-icons

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 13:00:27 -04:00
Carlos Alcaide CorvoandRandall Morey 9becadd3f1 chore: 🤖 Update @glimmer (#1161)
Update @glimmer

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 12:08:00 -04:00
Carlos Alcaide CorvoandRandall Morey 9f45a9a955 chore: 🤖 Update @ember/render-modifiers (#1158)
Update @ember/render-modifiers

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 11:34:31 -04:00
Carlos Alcaide CorvoandRandall Morey 51b94f7ac8 Chore update babel eslint parser (#1155)
* chore: 🤖 Fix merging conflicts

* chore: 🤖 Fix merging conflicts

Co-authored-by: Randall Morey <randall@randallmorey.com>
2022-06-29 10:51:41 -04:00
Randall Morey 890cfe5168 Refactor attributes fragments (#1156)
* refactor: 💡 migrate managed-group off fragments

* refactor: 💡 migrate credential-store off fragments

* refactor: 💡 migrate credential-library off fragments

* refactor: 💡 migrate account off fragments
2022-06-28 19:30:26 -04:00
Dharini Jeeva fe225653ec fix: 🐛 overflow dropdown ui issue (#1160) 2022-06-28 13:13:09 -07:00
Carlos Alcaide Corvo dce7447880 chore: 🤖 Upgrade @babel/core (#1153)
Upgrade @babel/core
2022-06-28 11:08:16 -07:00
Carlos Alcaide Corvo 330c3de256 Chore upgrade desktop dependencies 2 (#1152) 2022-06-28 10:27:47 -07:00
Carlos Alcaide Corvo 2d15a62990 fix: 🐛 Lock file discrepancy (#1154)
Lock file discrepancy
2022-06-27 14:38:51 -07:00
Zhihe Li 62af6e2f6e Use precommit hooks (#1150)
* chore: 🤖 Add husky and hooks

* chore: 🤖 Add lint staged for fixing lint issues

* chore: 🤖 Use prettier and disable conflicting prettier rules

* docs: ✏️ Update commit documentation in README
2022-06-27 14:35:52 -04:00
Carlos Alcaide Corvo f50acc9913 Chore upgrade desktop dependencies (#1151) 2022-06-27 09:33:10 -07:00
829 changed files with 16548 additions and 6622 deletions

No files matched your search

+26 -2
View File
@@ -45,7 +45,7 @@ jobs:
with: with:
name: admin-ui name: admin-ui
path: ./ui/admin/dist/ path: ./ui/admin/dist/
- name: Upload artifact Admin UI OSS - name: Upload artifact OSS admin UI
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: admin-ui-oss name: admin-ui-oss
@@ -69,8 +69,32 @@ jobs:
node-version: '16.x' node-version: '16.x'
if: steps.node-modules-cache.outputs.cache-hit != 'true' if: steps.node-modules-cache.outputs.cache-hit != 'true'
- run: yarn run build:ui:admin:enterprise - run: yarn run build:ui:admin:enterprise
- name: Upload artifact Admin UI Enterprise - name: Upload artifact enterprise admin UI
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: admin-ui-ent name: admin-ui-ent
path: ./ui/admin/dist/ path: ./ui/admin/dist/
build-admin-ui-hcp:
name: Build Admin UI HCP
needs: [dependencies]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
id: node-modules-cache
with:
path: '**/node_modules'
key: node-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
node-modules-
- name: Build
uses: actions/setup-node@v3
with:
node-version: '16.x'
if: steps.node-modules-cache.outputs.cache-hit != 'true'
- run: yarn run build:ui:admin:hcp
- name: Upload artifact HCP admin UI
uses: actions/upload-artifact@v3
with:
name: admin-ui-hcp
path: ./ui/admin/dist/
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn compliance:licenses
npx lint-staged
yarn test
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
# Don't run commitizen for merge or squash commits
if [ "${COMMIT_SOURCE}" = merge ] || [ "${COMMIT_SOURCE}" = squash ];then
exit 0
fi
# This is to allow interaction with the terminal for commitizen
exec < /dev/tty && npx git-cz --hook || true
+7 -7
View File
@@ -66,7 +66,6 @@ List of available project commands. `yarn run <command-name>`
|---------------------|---| |---------------------|---|
| build | Builds Admin UI. | | build | Builds Admin UI. |
| test | Runs tests in CI mode. | | test | Runs tests in CI mode. |
| commit | Replaces `git commit`, ensures compliance, audit, lint, and test checks pass before commit is allowed and normalizes commit messages across authors. |
| lint | Runs ember-template-lint on all of the hbs, js, and sass files. | | lint | Runs ember-template-lint on all of the hbs, js, and sass files. |
| compliance:audit | Checks for issues using `yarn audit` with moderate and above criticality.| | compliance:audit | Checks for issues using `yarn audit` with moderate and above criticality.|
| compliance:licenses | Checks that all dependencies have OSS-compatible licenses. | | compliance:licenses | Checks that all dependencies have OSS-compatible licenses. |
@@ -160,15 +159,16 @@ You will need to turn `off` mirage and run it: `$ ENABLE_MIRAGE=false yarn start
In login screen, authenticate using generated admin login name and password. In login screen, authenticate using generated admin login name and password.
Enter the origin of your Boundary dev instance, by default is: `http://localhost:9200`. Enter the cluster URL of your Boundary dev instance, by default is: `http://localhost:9200`.
### Committing ### Committing
Instead of the default `git commit`, we prescribe a custom command that ensures We use `husky` and `lint-staged` to ensure linting and other checks pass before a
linting and other checks pass before a commit may be completed. It also ensures commit is completed. Simply do a `yarn install` to make sure the hooks are installed.
that all contributors author consistent commit messages. To get started with a
commit, stage your files as usual. Then run `yarn commit` and follow the Use a normal `git commit` to go through the checks, if you need to skip these checks,
on-screen instructions to author your message. use `git commit --no-verify` to bypass them. However, a consistent commit message will
still be enforced even if you use `--no-verify`.
#### License Checking #### License Checking
+1 -5
View File
@@ -14,11 +14,7 @@ module.exports = {
// end of babel-config // end of babel-config
}, },
plugins: ['ember'], plugins: ['ember'],
extends: [ extends: ['eslint:recommended', 'plugin:ember/recommended', 'prettier'],
'eslint:recommended',
'plugin:ember/recommended',
'plugin:prettier/recommended',
],
env: { env: {
browser: true, browser: true,
}, },
+1 -1
View File
@@ -1,5 +1,5 @@
'use strict'; 'use strict';
module.exports = { module.exports = {
extends: 'octane', extends: ['recommended', 'stylistic'],
}; };
@@ -0,0 +1,15 @@
import ModelAbility from './model';
/**
* Provides abilities for credential.
*/
export default class CredentialLibaryAbility extends ModelAbility {
// =permissions
/**
* Only "known" credential libary types may be read.
* @type {boolean}
*/
get canRead() {
return !this.model.isUnknown && this.hasAuthorizedAction('read');
}
}
@@ -1,9 +1,13 @@
import ModelAbility from './model'; import ModelAbility from './model';
import { inject as service } from '@ember/service';
/** /**
* Provides abilities for credential store. * Provides abilities for credential store.
*/ */
export default class CredentialStoreAbility extends ModelAbility { export default class CredentialStoreAbility extends ModelAbility {
// =services
@service features;
// =permissions // =permissions
/** /**
@@ -11,6 +15,8 @@ export default class CredentialStoreAbility extends ModelAbility {
* @type {boolean} * @type {boolean}
*/ */
get canRead() { get canRead() {
return !this.model.isStatic && this.hasAuthorizedAction('read'); return this.features.isEnabled('static-credentials')
? this.hasAuthorizedAction('read')
: !this.model.isStatic && this.hasAuthorizedAction('read');
} }
} }
+15
View File
@@ -0,0 +1,15 @@
import ModelAbility from "./model";
/**
* Provides abilities for credential.
*/
export default class CredentialAbility extends ModelAbility {
// =permissions
/**
* Only "known" credential types may be read.
* @type {boolean}
*/
get canRead() {
return !this.model.isUnknown && this.hasAuthorizedAction('read');
}
}
+9 -1
View File
@@ -30,10 +30,18 @@ export default class TargetAbility extends ModelAbility {
/** /**
* @type {boolean} * @type {boolean}
*/ */
get canAddCredentialSources() { get canAddBrokeredCredentialSources() {
return this.hasAuthorizedAction('add-credential-sources'); return this.hasAuthorizedAction('add-credential-sources');
} }
/**
* @type {boolean}
*/
get canAddInjectedApplicationCredentialSources() {
return (
this.model.isSSH && this.hasAuthorizedAction('add-credential-sources')
);
}
/** /**
* @type {boolean} * @type {boolean}
*/ */
+15
View File
@@ -0,0 +1,15 @@
import ModelAbility from './model';
/**
* Provides abilities for workers.
*/
export default class WorkerAbility extends ModelAbility {
// =permissions
/**
* @type {boolean}
*/
get canCreateWorkerLed() {
return this.hasAuthorizedCollectionAction('create:worker-led');
}
}
@@ -43,4 +43,20 @@ export default class GeneratedAccountModel extends BaseModel {
description: 'Current version number of this resource.', description: 'Current version number of this resource.',
}) })
version; version;
// =attributes (password)
@attr('string', {
for: 'password',
isNestedAttribute: true,
description: 'The account login name',
})
login_name;
// =attributes (OIDC)
@attr('string', { for: 'oidc', isNestedAttribute: true }) subject;
@attr('string', { for: 'oidc', isNestedAttribute: true }) issuer;
@attr('string', { for: 'oidc', isNestedAttribute: true, readOnly: true })
email;
@attr('string', { for: 'oidc', isNestedAttribute: true, readOnly: true })
full_name;
} }
@@ -44,4 +44,27 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
description: 'Current version number of this resource.', description: 'Current version number of this resource.',
}) })
version; version;
//= attributes (vault)
@attr('string', {
isNestedAttribute: true,
description:
'The HTTP method the library uses when requesting credentials from Vault.',
defaultValue: () => 'GET',
})
http_method;
@attr('string', {
isNestedAttribute: true,
description:
'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.',
})
http_request_body;
@attr('string', {
isNestedAttribute: true,
description: 'The path in Vault to request credentials from.',
})
path;
} }
@@ -39,4 +39,90 @@ export default class GeneratedCredentialStoreModel extends BaseModel {
description: 'Current version number of this resource.', description: 'Current version number of this resource.',
}) })
version; version;
// =attributes (vault)
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description:
"The address to Vault server. This should be a complete URL such as 'https://127.0.0.1:8200'",
})
address;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description: 'The namespace within Vault to use.',
})
namespace;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description:
"A PEM-encoded CA certificate to verify the Vault server's TLS certificate.",
})
ca_cert;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description:
'Name to use as the SNI host when connecting to Vault via TLS.',
})
tls_server_name;
@attr('boolean', {
for: 'vault',
isNestedAttribute: true,
description: 'Whether or not to skip TLS verification.',
})
tls_skip_verify;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description: 'A token used for accessing Vault.',
})
token;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description: 'The Vault token hmac.',
readOnly: true,
})
token_hmac;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description:
'A PEM-encoded client certificate to use for TLS authentication to the Vault server.',
})
client_certificate;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description:
"A PEM-encoded private key matching the client certificate from 'client_certificate'.",
})
client_certificate_key;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description: 'The Vault client certificate key hmac.',
readOnly: true,
})
client_certificate_key_hmac;
@attr('string', {
for: 'vault',
isNestedAttribute: true,
description:
'Filters to the worker(s) who can handle Vault requests for this cred store.',
})
worker_filter;
} }
@@ -0,0 +1,79 @@
import BaseModel from '../../models/base';
import { attr } from '@ember-data/model';
/**
* A credential is a data structure containing one or more secrets that binds an
* identity to a set of permissions or capabilities on a host for a session.
*/
export default class GeneratedCredentialModel extends BaseModel {
// =attributes
@attr('string', {
description:
'The ID of the Credential Store of which this Credential is a part.',
})
credential_store_id;
@attr('string', {
description: 'The type of the resource, to help differentiate schemas',
})
type;
@attr('string', {
description: 'Optional name for identification purposes',
})
name;
@attr('string', {
description: 'Optional user-set description for identification purposes',
})
description;
@attr('date', {
description: 'The time this resource was created\nOutput only.',
readOnly: true,
})
created_time;
@attr('date', {
description: 'The time this resource was last updated\nOutput only.',
readOnly: true,
})
updated_time;
@attr('number', {
description: 'Current version number of this resource.',
})
version;
// =attributes (username_password, ssh_private_key)
@attr('string', {
for: ['username_password', 'ssh_private_key'],
isNestedAttribute: true,
description: 'The username for credential.',
})
username;
// =attributes (username_password)
@attr('string', {
for: 'username_password',
isNestedAttribute: true,
description: 'The password for credential.',
})
password;
// =attributes (ssh_private_key)
@attr('string', {
for: 'ssh_private_key',
isNestedAttribute: true,
description: 'The private key for credential.',
})
private_key;
@attr('string', {
for: 'ssh_private_key',
isNestedAttribute: true,
description: 'The private key passphrase for credential.',
})
private_key_passphrase;
}
@@ -44,4 +44,13 @@ export default class GeneratedManagedGroupModel extends BaseModel {
'The ID of the Auth Method that is associated with this ManagedGroup', 'The ID of the Auth Method that is associated with this ManagedGroup',
}) })
auth_method_id; auth_method_id;
// =attributes (OIDC)
@attr('string', {
isNestedAttribute: true,
description:
'The boolean expression filter to use to determine membership.',
})
filter;
} }
@@ -30,7 +30,6 @@ export default class GeneratedTargetModel extends BaseModel {
@attr('number', { @attr('number', {
description: '', description: '',
defaultValue: 1,
}) })
session_connection_limit; session_connection_limit;
@@ -0,0 +1,70 @@
import BaseModel from '../../models/base';
import { attr } from '@ember-data/model';
/**
* Worker contains all fields related to a worker resource
*/
export default class GeneratedWorkerModel extends BaseModel {
// =attributes
@attr('string', {
description: 'Optional name for identification purposes.',
})
name;
@attr('string', {
description: 'Optional user-set description for identification purposes.',
})
description;
@attr('date', {
description: 'The time this resource was created\nOutput only.',
readOnly: true,
})
created_time;
@attr('date', {
description: 'The time this resource was last updated\nOutput only.',
readOnly: true,
})
updated_time;
@attr('number', {
description: 'Current version number of this resource.',
})
version;
@attr('string', {
description: 'The address that this worker is reachable at.\nOutput only.',
readOnly: true,
})
address;
@attr('date', {
description:
'The time this worker was last reported its status.\nOutput only.',
readOnly: true,
})
last_status_time;
@attr('string', {
description:
'The version of the Boundary binary the worker is running.\nOutput only.',
readOnly: true,
})
release_version;
@attr('number', {
description:
'The number of connections that this worker is currently handling.\nOutput only.',
readOnly: true,
})
active_connection_count;
@attr('string', {
description:
'The type of the worker, denoted by how it authenticates: pki or kms.\nOutput only.',
readOnly: true,
})
type;
}
+2 -9
View File
@@ -1,17 +1,10 @@
import GeneratedAccountModel from '../generated/models/account'; import GeneratedAccountModel from '../generated/models/account';
import { fragment } from 'ember-data-model-fragments/attributes';
import { computed } from '@ember/object'; import { computed } from '@ember/object';
import { equal } from '@ember/object/computed'; import { equal } from '@ember/object/computed';
export default class AccountModel extends GeneratedAccountModel { export default class AccountModel extends GeneratedAccountModel {
// =attributes // =attributes
/**
* Attributes of this resource, if any, represented as a JSON fragment.
* @type {FragmentAccountAttributesModel}
*/
@fragment('fragment-account-attributes', { defaultValue: {} }) attributes;
/** /**
* @type {boolean} * @type {boolean}
*/ */
@@ -26,9 +19,9 @@ export default class AccountModel extends GeneratedAccountModel {
* Convenience for getting username in account. * Convenience for getting username in account.
* @type {string} * @type {string}
*/ */
@computed('attributes.{email,full_name,login_name}') @computed('{email,full_name,login_name}')
get accountName() { get accountName() {
const { email, full_name, login_name } = this.attributes; const { email, full_name, login_name } = this;
return email || full_name || login_name; return email || full_name || login_name;
} }
+5 -3
View File
@@ -1,6 +1,5 @@
import Model from '@ember-data/model'; import Model from '@ember-data/model';
import { attr } from '@ember-data/model'; import { attr } from '@ember-data/model';
import { fragment } from 'ember-data-model-fragments/attributes';
import { computed } from '@ember/object'; import { computed } from '@ember/object';
/** /**
@@ -30,9 +29,8 @@ export default class BaseModel extends Model {
/** /**
* Scope of this resource, if any, represented as a JSON fragment. * Scope of this resource, if any, represented as a JSON fragment.
* @type {FragmentScope}
*/ */
@fragment('fragment-scope') scope; @attr() scope;
// =attributes // =attributes
@@ -55,6 +53,10 @@ export default class BaseModel extends Model {
if (model) { if (model) {
const json = model.serialize(); const json = model.serialize();
json.scope_id = model.id; json.scope_id = model.id;
json.type = model.type;
json.isGlobal = model.isGlobal;
json.isOrg = model.isOrg;
json.isProject = model.isProject;
this.scope = json; this.scope = json;
} }
} }
+18 -15
View File
@@ -1,6 +1,4 @@
import GeneratedCredentialLibraryModel from '../generated/models/credential-library'; import GeneratedCredentialLibraryModel from '../generated/models/credential-library';
import { attr } from '@ember-data/model';
import { fragment } from 'ember-data-model-fragments/attributes';
/** /**
* Enum options for credential library. * Enum options for credential library.
@@ -9,22 +7,27 @@ export const options = {
http_method: ['GET', 'POST'], http_method: ['GET', 'POST'],
}; };
/**
* Supported Credential Library types.
*/
export const types = ['vault'];
export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel { export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel {
// =error attributes
// These attributes exist solely to capture errors on nested fields.
// See the application adapter's error normalization method for
// more information.
@attr('string', { readOnly: true }) attributes_http_method;
@attr('string', { readOnly: true }) attributes_http_request_body;
@attr('string', { readOnly: true }) attributes_path;
// =attributes // =attributes
/** /**
* Attributes of this resource, if any, represented as a JSON fragment. * True if credential is an unknown type.
* @type {FragmentCredentialLibraryAttributesModel} * @type {boolean}
*/ */
@fragment('fragment-credential-library-attributes', { defaultValue: {} }) get isUnknown() {
attributes; return !types.includes(this.type);
}
/**
* True if credential is a vault type.
* @type {boolean}
*/
get isVault() {
return this.type === 'vault';
}
} }
@@ -1,32 +1,9 @@
import GeneratedCredentialStoreModel from '../generated/models/credential-store'; import GeneratedCredentialStoreModel from '../generated/models/credential-store';
import { attr } from '@ember-data/model';
import { fragment } from 'ember-data-model-fragments/attributes';
import { equal } from '@ember/object/computed'; import { equal } from '@ember/object/computed';
export default class CredentialStoreModel extends GeneratedCredentialStoreModel { export default class CredentialStoreModel extends GeneratedCredentialStoreModel {
// =error attributes
// These attributes exist solely to capture errors on nested fields.
// See the application adapter's error normalization method for
// more information.
@attr('string', { readOnly: true }) attributes_address;
@attr('string', { readOnly: true }) attributes_namespace;
@attr('string', { readOnly: true }) attributes_ca_cert;
@attr('string', { readOnly: true }) attributes_tls_server_name;
@attr('string', { readOnly: true }) attributes_tls_skip_verify;
@attr('string', { readOnly: true }) attributes_token;
@attr('string', { readOnly: true }) attributes_client_certificate;
@attr('string', { readOnly: true }) attributes_client_certificate_key;
// =attributes // =attributes
/**
* Attributes of this resource, if any, represented as a JSON fragment.
* @type {FragmentAuthMethodAttributesModel}
*/
@fragment('fragment-credential-store-attributes', { defaultValue: {} })
attributes;
/** /**
* @type {boolean} * @type {boolean}
*/ */
+28
View File
@@ -0,0 +1,28 @@
import GeneratedCredentialModel from '../generated/models/credential';
/**
* Supported Credential types.
*/
export const types = ['username_password', 'ssh_private_key'];
export default class CredentialModel extends GeneratedCredentialModel {
// =attributes
/**
* All Credentials are prefixed with "cred" and are considered
* static due to their relation with Static Credential Stores.
*
* True if credential starts with the "cred" prefix.
* @type {boolean}
*/
get isStatic() {
return this.id.startsWith('cred');
}
/**
* True if credential is an unknown type.
* @type {boolean}
*/
get isUnknown() {
return !types.includes(this.type);
}
}
@@ -1,17 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentAccountAttributesModel extends Fragment {
// =attributes (password)
@attr('string', {
for: 'password',
description: 'The account login name',
})
login_name;
// =attributes (OIDC)
@attr('string', { for: 'oidc' }) subject;
@attr('string', { for: 'oidc' }) issuer;
@attr('string', { for: 'oidc', readOnly: true }) email;
@attr('string', { for: 'oidc', readOnly: true }) full_name;
}
@@ -1,25 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
import { options } from './credential-library';
export default class FragmentCredentialLibraryAttributesModel extends Fragment {
//= attributes (vault)
@attr('string', {
description:
'The HTTP method the library uses when requesting credentials from Vault.',
defaultValue: () => options.http_method[0],
})
http_method;
@attr('string', {
description:
'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.',
})
http_request_body;
@attr('string', {
description: 'The path in Vault to request credentials from.',
})
path;
}
@@ -1,72 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentCredentialStoreAttributesModel extends Fragment {
// =attributes (vault)
@attr('string', {
for: 'vault',
description:
"The address to Vault server. This should be a complete URL such as 'https://127.0.0.1:8200'",
})
address;
@attr('string', {
for: 'vault',
description: 'The namespace within Vault to use.',
})
namespace;
@attr('string', {
for: 'vault',
description:
"A PEM-encoded CA certificate to verify the Vault server's TLS certificate.",
})
ca_cert;
@attr('string', {
for: 'vault',
description:
'Name to use as the SNI host when connecting to Vault via TLS.',
})
tls_server_name;
@attr('boolean', {
for: 'vault',
description: 'Whether or not to skip TLS verification.',
})
tls_skip_verify;
@attr('string', {
for: 'vault',
description: 'A token used for accessing Vault.',
})
token;
@attr('string', {
for: 'vault',
description: 'The Vault token hmac.',
readOnly: true,
})
token_hmac;
@attr('string', {
for: 'vault',
description:
'A PEM-encoded client certificate to use for TLS authentication to the Vault server.',
})
client_certificate;
@attr('string', {
for: 'vault',
description:
"A PEM-encoded private key matching the client certificate from 'client_certificate'.",
})
client_certificate_key;
@attr('string', {
for: 'vault',
description: 'The Vault client certificate key hmac.',
readOnly: true,
})
client_certificate_key_hmac;
}
@@ -1,16 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentHostSourceModel extends Fragment {
// =attributes
@attr('string', {
description: 'ID of the related host source',
})
host_source_id;
@attr('string', {
description: 'ID of the catalog to which the host set belongs',
})
host_catalog_id;
}
@@ -1,12 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentManagedGroupAttributesModel extends Fragment {
// =attributes (OIDC)
@attr('string', {
description:
'The boolean expression filter to use to determine membership.',
})
filter;
}
@@ -1,21 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentPrincipal extends Fragment {
// =attributes
@attr('string', {
description: 'ID of the related scope',
})
scope_id;
@attr('string', {
description: 'ID of the related principal (user or group)',
})
principal_id;
@attr('string', {
description: 'Type of the related principal (user or group)',
})
type;
}
-42
View File
@@ -1,42 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { computed } from '@ember/object';
import { attr } from '@ember-data/model';
import { scopeTypes } from './scope';
export default class FragmentScope extends Fragment {
// =attributes
@attr('string', {
description: 'ID of the related scope',
})
scope_id;
@attr('string', {
description: 'The type of the resource',
})
type;
/**
* @type {boolean}
*/
@computed('type')
get isGlobal() {
return this.type === scopeTypes.global;
}
/**
* @type {boolean}
*/
@computed('type')
get isOrg() {
return this.type === scopeTypes.org;
}
/**
* @type {boolean}
*/
@computed('type')
get isProject() {
return this.type === scopeTypes.project;
}
}
-9
View File
@@ -1,16 +1,10 @@
import GeneratedManagedGroupModel from '../generated/models/managed-group'; import GeneratedManagedGroupModel from '../generated/models/managed-group';
import { attr } from '@ember-data/model'; import { attr } from '@ember-data/model';
import { fragment } from 'ember-data-model-fragments/attributes';
import { A } from '@ember/array'; import { A } from '@ember/array';
export default class ManagedGroupModel extends GeneratedManagedGroupModel { export default class ManagedGroupModel extends GeneratedManagedGroupModel {
// =attributes // =attributes
// =error attributes
// These attributes exist solely to capture errors on nested fields.
// See the application adapter's error normalization method for
// more information.
@attr('string', { readOnly: true }) attributes_filter; @attr('string', { readOnly: true }) attributes_filter;
/** /**
@@ -23,7 +17,4 @@ export default class ManagedGroupModel extends GeneratedManagedGroupModel {
emptyArrayIfMissing: true, emptyArrayIfMissing: true,
}) })
member_ids; member_ids;
@fragment('fragment-managed-group-attributes', { defaultValue: {} })
attributes;
} }
+6 -4
View File
@@ -1,5 +1,5 @@
import GeneratedRoleModel from '../generated/models/role'; import GeneratedRoleModel from '../generated/models/role';
import { fragmentArray, array } from 'ember-data-model-fragments/attributes'; import { attr } from '@ember-data/model';
export default class RoleModel extends GeneratedRoleModel { export default class RoleModel extends GeneratedRoleModel {
// =attributes // =attributes
@@ -11,7 +11,7 @@ export default class RoleModel extends GeneratedRoleModel {
* see obvious. Instead, the application layer is expected to load referenced * see obvious. Instead, the application layer is expected to load referenced
* users and groups as needed. * users and groups as needed.
*/ */
@fragmentArray('fragment-principal', { @attr('principal-array', {
readOnly: true, readOnly: true,
emptyArrayIfMissing: true, emptyArrayIfMissing: true,
}) })
@@ -21,13 +21,15 @@ export default class RoleModel extends GeneratedRoleModel {
* Grant strings are read-only. But grants can be persisted via a dedicated * Grant strings are read-only. But grants can be persisted via a dedicated
* call to `saveGrantStrings(grants)`. * call to `saveGrantStrings(grants)`.
*/ */
@array('string', { readOnly: true }) grant_strings; @attr({ readOnly: true, emptyArrayIfMissing: true }) grant_strings;
/** /**
* Convenience for looking up the grant scope, if loaded. * Convenience for looking up the grant scope, if loaded.
*/ */
get grantScope() { get grantScope() {
return this.store.peekRecord('scope', this.grant_scope_id); return this.grant_scope_id
? this.store.peekRecord('scope', this.grant_scope_id)
: null;
} }
// =methods // =methods
+132 -31
View File
@@ -1,35 +1,43 @@
import GeneratedTargetModel from '../generated/models/target'; import GeneratedTargetModel from '../generated/models/target';
import { attr } from '@ember-data/model'; import { attr } from '@ember-data/model';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
import { computed } from '@ember/object';
export default class TargetModel extends GeneratedTargetModel { export default class TargetModel extends GeneratedTargetModel {
// =attributes // =attributes
@attr('number', { @attr('number', {
isNestedAttribute: true, isNestedAttribute: true,
description: 'The default port a target should use if present.', description: 'The default port a target should use if present.',
}) })
default_port; default_port;
/** /**
* @type {[FragmentHostSourceModel]} * @type Array
*/ */
@fragmentArray('fragment-host-source', { @attr('host-source-id-array', {
readOnly: true, readOnly: true,
emptyArrayIfMissing: true, emptyArrayIfMissing: true,
}) })
host_sources; host_sources;
/** /**
* Credential source ids are read only and can be * Brokered Credential source ids are read only and can be
* persisted via a dedicated call to `addCredentialSources()`. * persisted via a dedicated call to `addBrokeredCredentialSources()`.
*/ */
@fragmentArray('fragment-string', { @attr('string-array', {
readOnly: true, readOnly: true,
emptyArrayIfMissing: true, emptyArrayIfMissing: true,
}) })
application_credential_source_ids; brokered_credential_source_ids;
/**
* Injected Application Credential source ids are read only and can be
* persisted via a dedicated call to `addInjectedApplicationCredentialSources()`.
*/
@attr('string-array', {
readOnly: true,
emptyArrayIfMissing: true,
})
injected_application_credential_source_ids;
/** /**
* An array of resolved host set and host catalog instances. Model instances * An array of resolved host set and host catalog instances. Model instances
@@ -37,7 +45,6 @@ export default class TargetModel extends GeneratedTargetModel {
* instances). Unresolvable instances are excluded from the array. * instances). Unresolvable instances are excluded from the array.
* @type {[{model: HostSetModel, hostCatalog: HostCatalogModel}]} * @type {[{model: HostSetModel, hostCatalog: HostCatalogModel}]}
*/ */
@computed('host_sources.[]', 'store')
get hostSets() { get hostSets() {
return this.host_sources return this.host_sources
.map(({ host_source_id, host_catalog_id }) => ({ .map(({ host_source_id, host_catalog_id }) => ({
@@ -48,17 +55,38 @@ export default class TargetModel extends GeneratedTargetModel {
} }
/** /**
* An array of resolved credential library instances. Model instances * An array of resolved credential library and credential instances. Model instances
* must already be loaded into the store (this method will not load unloaded * must already be loaded into the store (this method will not load unloaded
* instances). Unresolvable instances are excluded from the array. * instances). Unresolvable instances are excluded from the array.
* @type {[CredentialLibraryModel]} * @type {[CredentialLibraryModel, CredentialModel]}
*/ */
@computed('application_credential_source_ids.[]', 'store') get brokeredCredentialSources() {
get credentialLibraries() { return this.brokered_credential_source_ids
return this.application_credential_source_ids .map((source) => {
.map((source) => if (source.value.startsWith('cred')) {
this.store.peekRecord('credential-library', source.value) return this.store.peekRecord('credential', source.value);
) } else {
return this.store.peekRecord('credential-library', source.value);
}
})
.filter(Boolean);
}
/**
* An array of resolved credential library and credential instances. Model instances
* must already be loaded into the store (this method will not load unloaded
* instances). Unresolvable instances are excluded from the array.
* @type {[CredentialLibraryModel, CredentialModel]}
*/
get injectedApplicationCredentialSources() {
return this.injected_application_credential_source_ids
.map((source) => {
if (source.value.startsWith('cred')) {
return this.store.peekRecord('credential', source.value);
} else {
return this.store.peekRecord('credential-library', source.value);
}
})
.filter(Boolean); .filter(Boolean);
} }
@@ -150,17 +178,20 @@ export default class TargetModel extends GeneratedTargetModel {
} }
/** /**
* Adds credential libraries via the `add-credential-sources` method. * Adds credential sources via the `add-credential-sources` method.
* See serializer and adapter for more information. * See serializer and adapter for more information.
* @param {[string]} credentialLibraryIDs * @param {[string]} brokeredCredentialSourceIDs
* @param {object} options * @param {object} options
* @param {object} options.adapterOptions * @param {object} options.adapterOptions
* @return {Promise} * @return {Promise}
*/ */
addCredentialSources(credentialLibraryIDs, options = { adapterOptions: {} }) { addBrokeredCredentialSources(
brokeredCredentialSourceIDs,
options = { adapterOptions: {} }
) {
const defaultAdapterOptions = { const defaultAdapterOptions = {
method: 'add-credential-sources', method: 'add-credential-sources',
credentialLibraryIDs, brokeredCredentialSourceIDs,
}; };
// There is no "deep merge" in ES. // There is no "deep merge" in ES.
return this.save({ return this.save({
@@ -173,20 +204,46 @@ export default class TargetModel extends GeneratedTargetModel {
} }
/** /**
* Delete credential libraries via the `remove-credential-sources` method. * Adds credential sources via the `add-credential-sources` method.
* See serializer and adapter for more information. * See serializer and adapter for more information.
* @param {[string]} credentialLibraryIDs * @param {[string]} injectedApplicationCredentialSourceIDs
* @param {object} options * @param {object} options
* @param {object} options.adapterOptions * @param {object} options.adapterOptions
* @return {Promise} * @return {Promise}
*/ */
removeCredentialSources( addInjectedApplicationCredentialSources(
credentialLibraryIDs, injectedApplicationCredentialSourceIDs,
options = { adapterOptions: {} }
) {
const defaultAdapterOptions = {
method: 'add-credential-sources',
injectedApplicationCredentialSourceIDs,
};
// There is no "deep merge" in ES.
return this.save({
...options,
adapterOptions: {
...defaultAdapterOptions,
...options.adapterOptions,
},
});
}
/**
* Delete credential libraries and credentials via the `remove-credential-sources` method.
* See serializer and adapter for more information.
* @param {[string]} brokeredCredentialSourceIDs
* @param {object} options
* @param {object} options.adapterOptions
* @return {Promise}
*/
removeBrokeredCredentialSources(
brokeredCredentialSourceIDs,
options = { adapterOptions: {} } options = { adapterOptions: {} }
) { ) {
const defaultAdapterOptions = { const defaultAdapterOptions = {
method: 'remove-credential-sources', method: 'remove-credential-sources',
credentialLibraryIDs, brokeredCredentialSourceIDs,
}; };
// There is no "deep merge" in ES. // There is no "deep merge" in ES.
return this.save({ return this.save({
@@ -199,15 +256,59 @@ export default class TargetModel extends GeneratedTargetModel {
} }
/** /**
* Delete a single credential library set via the `remove-credential-sources` method. * Delete a single credential library/credential set via the `remove-credential-sources` method.
* @param {number} credentialLibraryID * @param {number} brokeredCredentialSourceID
* @param {object} options * @param {object} options
* @return {Promise} * @return {Promise}
*/ */
removeCredentialSource(credentialLibraryID, options) { removeBrokeredCredentialSource(brokeredCredentialSourceID, options) {
return this.removeCredentialSources([credentialLibraryID], options); return this.removeBrokeredCredentialSources(
[brokeredCredentialSourceID],
options
);
} }
/**
* Delete credential libraries and credentials via the `remove-credential-sources` method.
* See serializer and adapter for more information.
* @param {[string]} injectedApplicationCredentialSourceIDs
* @param {object} options
* @param {object} options.adapterOptions
* @return {Promise}
*/
removeInjectedApplicationCredentialSources(
injectedApplicationCredentialSourceIDs,
options = { adapterOptions: {} }
) {
const defaultAdapterOptions = {
method: 'remove-credential-sources',
injectedApplicationCredentialSourceIDs,
};
// There is no "deep merge" in ES.
return this.save({
...options,
adapterOptions: {
...defaultAdapterOptions,
...options.adapterOptions,
},
});
}
/**
* Delete a single credential library/credential set via the `remove-credential-sources` method.
* @param {number} injectedApplicationCredentialSourceID
* @param {object} options
* @return {Promise}
*/
removeInjectedApplicationCredentialSource(
injectedApplicationCredentialSourceID,
options
) {
return this.removeInjectedApplicationCredentialSources(
[injectedApplicationCredentialSourceID],
options
);
}
/** /**
* True if the target type is tcp. * True if the target type is tcp.
* @type {boolean} * @type {boolean}
+88
View File
@@ -0,0 +1,88 @@
import GeneratedWorkerModel from '../generated/models/worker';
import { attr } from '@ember-data/model';
export default class WorkerModel extends GeneratedWorkerModel {
// =attributes
/**
* Names are optional on models in our API. Thus we need to fallback on ID
* for display purposes.
* @type {string}
*/
get displayName() {
return this.name || this.id;
}
/**
* Returns whether the worker is a pki worker.
* @type {boolean}
*/
get isPki() {
return this.type === 'pki';
}
/**
* Returns the number of config tags present on the worker.
* @type {number}
*/
get tagCount() {
if (!this.config_tags) {
return 0;
}
return Object.values(this.config_tags).reduce(
(previousCount, currentTags) => previousCount + currentTags.length,
0
);
}
/**
* Returns the config tags as an array of key/value pair objects.
* @type {[object]}
*/
getConfigTagList() {
if (!this.config_tags) {
return null;
}
return Object.entries(this.config_tags).flatMap(([key, value]) =>
value.map((tag) => ({ key, value: tag }))
);
}
@attr({
description:
'The deduplicated union of the tags reported by the worker ' +
'from its configuration and any tags added through other means.\nOutput only.',
readOnly: true,
})
canonical_tags;
@attr({
description:
"The tags set in the worker's configuration file.\nOutput only.",
readOnly: true,
})
config_tags;
/**
* Method to modify the adapter to handle custom POST route for creating worker.
* @param {string} workerGeneratedAuthToken
* @param {object} options
* @param {object} options.adapterOptions
* @return {Promise}
*/
createWorkerLed(workerGeneratedAuthToken, options = { adapterOptions: {} }) {
const defaultAdapterOptions = {
method: 'create:worker-led',
workerGeneratedAuthToken,
};
return super.save({
...options,
adapterOptions: {
...defaultAdapterOptions,
...options.adapterOptions,
},
});
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ export default class AccountSerializer extends ApplicationSerializer {
delete serialized.attributes; delete serialized.attributes;
if (isNew) { if (isNew) {
serialized.attributes = {}; serialized.attributes = {};
const { issuer, subject } = snapshot.attr('attributes').record; const { issuer, subject } = snapshot.record;
if (issuer) serialized.attributes.issuer = issuer; if (issuer) serialized.attributes.issuer = issuer;
if (subject) serialized.attributes.subject = subject; if (subject) serialized.attributes.subject = subject;
} }
+10 -5
View File
@@ -96,7 +96,7 @@ export default class ApplicationSerializer extends RESTSerializer {
delete serialized.scope; delete serialized.scope;
// And serialize `scope_id` // And serialize `scope_id`
if (this.serializeScopeID) { if (this.serializeScopeID) {
const scope_id = snapshot?.attr('scope')?.attr('scope_id'); const scope_id = snapshot?.attr('scope')?.scope_id;
if (scope_id) serialized.scope_id = scope_id; if (scope_id) serialized.scope_id = scope_id;
} }
return serialized; return serialized;
@@ -199,11 +199,9 @@ export default class ApplicationSerializer extends RESTSerializer {
} }
/** /**
* One consequence of using model fragments to represent the embedded scope * Hydrates the incoming scope JSON with additional boolean fields and
* is that they cannot have `id` fields. We still need to know scope IDs, * delegates nested attributes and secrets normalization.
* so we copy the `scope.id` value into the `scope.scope_id` field.
* @override * @override
* @see FragmentScope
* @param {Model} typeClass * @param {Model} typeClass
* @param {Object} hash * @param {Object} hash
* @return {Object} * @return {Object}
@@ -211,7 +209,14 @@ export default class ApplicationSerializer extends RESTSerializer {
normalize(typeClass, hash) { normalize(typeClass, hash) {
let normalizedHash = copy(hash, true); let normalizedHash = copy(hash, true);
const scopeID = get(normalizedHash, 'scope.id'); const scopeID = get(normalizedHash, 'scope.id');
const scopeType = get(normalizedHash, 'scope.type');
if (scopeID) normalizedHash.scope.scope_id = scopeID; if (scopeID) normalizedHash.scope.scope_id = scopeID;
if (scopeType) {
normalizedHash.scope.type = scopeType;
normalizedHash.scope.isGlobal = scopeType === 'global';
normalizedHash.scope.isOrg = scopeType === 'org';
normalizedHash.scope.isProject = scopeType === 'project';
}
normalizedHash = this.normalizeNestedAttributes(typeClass, normalizedHash); normalizedHash = this.normalizeNestedAttributes(typeClass, normalizedHash);
normalizedHash = this.normalizeNestedSecrets(typeClass, normalizedHash); normalizedHash = this.normalizeNestedSecrets(typeClass, normalizedHash);
return super.normalize(typeClass, normalizedHash); return super.normalize(typeClass, normalizedHash);
@@ -81,7 +81,6 @@ export default class AuthMethodSerializer extends ApplicationSerializer {
* *
* TODO: generalize this so that all zero values are reified. * TODO: generalize this so that all zero values are reified.
* @override * @override
* @see FragmentScope
* @param {Model} typeClass * @param {Model} typeClass
* @param {Object} hash * @param {Object} hash
* @return {Object} * @return {Object}
@@ -1,3 +1,25 @@
import ApplicationSerializer from './application'; import ApplicationSerializer from './application';
export default class CredentialLibrarySerializer extends ApplicationSerializer {} export default class CredentialLibrarySerializer extends ApplicationSerializer {
// =properties
/**
* @type {boolean}
*/
serializeScopeID = false;
/**
* @override
* @method serialize
* @param {Snapshot} snapshot
*/
serialize() {
const serialized = super.serialize(...arguments);
if (serialized.attributes) {
// Serialize `http_request_body` only if `http_method` is POST
if (!serialized.attributes?.http_method?.match(/post/i))
delete serialized.attributes.http_request_body;
}
return serialized;
}
}
@@ -1,3 +1,50 @@
import ApplicationSerializer from './application'; import ApplicationSerializer from './application';
import { copy } from 'ember-copy';
export default class CredentialStoreSerializer extends ApplicationSerializer {} export default class CredentialStoreSerializer extends ApplicationSerializer {
/**
* @override
* @method serialize
* @param {Snapshot} snapshot
*/
serialize(snapshot) {
switch (snapshot.record.type) {
case 'vault':
return this.serializeVault(...arguments);
case 'static':
default:
return this.serializeStatic(...arguments);
}
}
serializeVault() {
const serialized = super.serialize(...arguments);
if (serialized.attributes) {
// Token cannot be unset. If it's falsy, it must be removed.
if (!serialized.attributes?.token) delete serialized.attributes.token;
// Client certificate key cannot be unset when certificate is set.
// If it's falsy, it must be removed.
if (
!serialized.attributes?.client_certificate_key &&
serialized.attributes?.client_certificate
)
delete serialized.attributes.client_certificate_key;
}
return serialized;
}
serializeStatic() {
const serialized = super.serialize(...arguments);
// Delete attributes for static cred store
delete serialized.attributes;
return serialized;
}
normalize(typeClass, hash, ...rest) {
const normalizedHash = copy(hash, true);
const normalized = super.normalize(typeClass, normalizedHash, ...rest);
// Remove secret fields as we don't track them after being created/updated
normalized.data.attributes.token = '';
return normalized;
}
}
@@ -0,0 +1,66 @@
import ApplicationSerializer from './application';
import { copy } from 'ember-copy';
export default class CredentialSerializer extends ApplicationSerializer {
/**
* @override
* @method serialize
* @param {Snapshot} snapshot
*/
/**
* @type {boolean}
*/
serializeScopeID = false;
serialize(snapshot) {
switch (snapshot.record.type) {
case 'username_password':
return this.serializeUsernamePassword(...arguments);
case 'ssh_private_key':
default:
return this.serializeSSHPrivateKey(...arguments);
}
}
serializeUsernamePassword() {
const serialized = super.serialize(...arguments);
// Remove non-username_password type attributes
delete serialized.attributes.private_key;
delete serialized.attributes.private_key_passphrase;
// Remove password from the payload if null
// or empty string. This allows the user to only update
// the username without providing the password again.
// Users cannot unset the password, they would have
// to delete the credential entirely.
if (!serialized?.attributes?.password)
delete serialized.attributes.password;
return serialized;
}
serializeSSHPrivateKey() {
const serialized = super.serialize(...arguments);
// Remove non-ssh_private_key type attributes
delete serialized.attributes.password;
// Remove private_key and/or private_key_passphrase from the payload
// if null or empty string. This allows the user to only update
// the username without providing the private key and passphrase again.
// Users cannot unset the private key or passphrase, they would have
// to delete the credential entirely.
if (!serialized?.attributes?.private_key_passphrase)
delete serialized.attributes.private_key_passphrase;
if (!serialized?.attributes?.private_key)
delete serialized.attributes.private_key;
return serialized;
}
normalize(typeClass, hash, ...rest) {
const normalizedHash = copy(hash, true);
const normalized = super.normalize(typeClass, normalizedHash, ...rest);
// Remove secret fields as we don't track them after being created/updated
normalized.data.attributes.password = '';
normalized.data.attributes.private_key = '';
normalized.data.attributes.private_key_passphrase = '';
return normalized;
}
}
@@ -1,26 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentAccountAttributesSerializer extends JSONSerializer {
/**
* If an attribute is annotated as readOnly in the model, don't serialize it.
* Otherwise delegate to default attribute serializer.
*
* @override
* @method serializeAttribute
* @param {Snapshot} snapshot
* @param {Object} json
* @param {String} key
* @param {Object} attribute
*/
serializeAttribute(snapshot, json, key, attribute) {
const { type, options } = attribute;
let value = super.serializeAttribute(...arguments);
// Convert empty strings to null.
if (type === 'string' && json[key] === '') json[key] = null;
// Do not serialize read-only attributes.
if (options.readOnly) delete json[key];
// Client secret cannot be unset. If it's falsy, it must be removed.
if (key === 'client_secret' && !json[key]) delete json[key];
return value;
}
}
@@ -1,27 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentCredentialLibraryAttributesSerializer extends JSONSerializer {
/**
* If an attribute is annotated as readOnly in the model, don't serialize it.
* Otherwise delegate to default attribute serializer.
* Only serialize http_request_body when `http_method` is set to `POST`.
* @override
* @method serializeAttribute
* @param {Snapshot} snapshot
* @param {Object} json
* @param {String} key
* @param {Object} attribute
*/
serializeAttribute(snapshot, json, key, attribute) {
const { type, options } = attribute;
let value = super.serializeAttribute(...arguments);
// Convert empty strings to null.
if (type === 'string' && json[key] === '') json[key] = null;
// Do not serialize read-only attributes.
if (options.readOnly) delete json[key];
// Do not serialize http_request_body unless http_method is POST
if (key === 'http_request_body' && !json['http_method']?.match(/post/i))
delete json[key];
return value;
}
}
@@ -1,34 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentCredentialStoreAttributesSerializer extends JSONSerializer {
/**
* If an attribute is annotated as readOnly in the model, don't serialize it.
* Otherwise delegate to default attribute serializer.
*
* @override
* @method serializeAttribute
* @param {Snapshot} snapshot
* @param {Object} json
* @param {String} key
* @param {Object} attribute
*/
serializeAttribute(snapshot, json, key, attribute) {
const { type, options } = attribute;
let value = super.serializeAttribute(...arguments);
// Convert empty strings to null.
if (type === 'string' && json[key] === '') json[key] = null;
// Do not serialize read-only attributes.
if (options.readOnly) delete json[key];
// Token cannot be unset. If it's falsy, it must be removed.
if (key === 'token' && !json[key]) delete json[key];
// Client certificate key cannot be unset when certificate is set.
// If it's falsy, it must be removed.
if (
key === 'client_certificate_key' &&
!json[key] &&
json['client_certificate']
)
delete json[key];
return value;
}
}
@@ -1,16 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentHostSourceSerializer extends JSONSerializer {
// =methods
/**
* Renames `id` to `host_source_id` because fragments may not have IDs.
* Otherwise normalizes as normal.
* @param {ModelClass} typeClass
* @param {object} resourceHash
* @return {object}
*/
normalize(typeClass, { id: host_source_id, ...obj }) {
return super.normalize(typeClass, { host_source_id, ...obj });
}
}
@@ -1,27 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentManagedGroupAttributesSerializer extends JSONSerializer {
/**
* If an attribute is annotated as readOnly in the model, don't serialize it.
* Otherwise delegate to default attribute serializer.
* @override
* @method serializeAttribute
* @param {Snapshot} snapshot
* @param {Object} json
* @param {String} key
* @param {Object} attribute
*/
serializeAttribute(snapshot, json, key, attribute) {
const { type, options } = attribute;
let value = super.serializeAttribute(...arguments);
// Convert empty string to null.
if (type === 'string' && json[key] === '') json[key] = null;
// Do not serialize read-only attributes.
if (options.readOnly) delete json[key];
// Version is sent only if it has a non-nullish value
if (key === 'version') {
if (json[key] === null || json[key] === undefined) delete json[key];
}
return value;
}
}
@@ -1,16 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentPrincipalSerializer extends JSONSerializer {
// =methods
/**
* Renames `id` to `principal_id` because fragments may not have IDs.
* Otherwise normalizes as normal.
* @param {ModelClass} typeClass
* @param {object} resourceHash
* @return {object}
*/
normalize(typeClass, { id: principal_id, ...obj }) {
return super.normalize(typeClass, { principal_id, ...obj });
}
}
+2 -2
View File
@@ -80,8 +80,8 @@ export default class HostSetSerializer extends ApplicationSerializer {
*/ */
normalize(typeClass, hash, ...rest) { normalize(typeClass, hash, ...rest) {
const normalizedHash = copy(hash, true); const normalizedHash = copy(hash, true);
if (typeof normalizedHash?.filters === 'string') { if (typeof normalizedHash?.attributes?.filters === 'string') {
normalizedHash.filters = [normalizedHash.filters]; normalizedHash.attributes.filters = [normalizedHash.attributes.filters];
} }
const normalized = super.normalize(typeClass, normalizedHash, ...rest); const normalized = super.normalize(typeClass, normalizedHash, ...rest);
return normalized; return normalized;
+40 -11
View File
@@ -7,10 +7,10 @@ export default class TargetSerializer extends ApplicationSerializer {
* If `adapterOptions.hostSets` is set to an array of host set models, * If `adapterOptions.hostSets` is set to an array of host set models,
* the resulting target serialization should include **only host sets** * the resulting target serialization should include **only host sets**
* and the version. * and the version.
* If `adapterOptions.credentialLibraries` is set to an array of * If `adapterOptions.credentialSources` is set to an array of
* credential library models, the resulting target serialization should * credential library and credential models, the resulting target serialization should
* include **only credential libraries** and the version. * include **only credential libraries and crendentials** and the version.
* Normally, neither host sets or credential libraries are not serialized. * Normally, neither host sets or credential libraries or credentials are not serialized.
* @override * @override
* @param {Snapshot} snapshot * @param {Snapshot} snapshot
* @return {object} * @return {object}
@@ -21,11 +21,20 @@ export default class TargetSerializer extends ApplicationSerializer {
if (hostSourceIDs) { if (hostSourceIDs) {
serialized = this.serializeWithHostSources(snapshot, hostSourceIDs); serialized = this.serializeWithHostSources(snapshot, hostSourceIDs);
} }
const credentialSourceIDs = snapshot?.adapterOptions?.credentialLibraryIDs; const brokeredCredentialSourceIDs =
if (credentialSourceIDs) snapshot?.adapterOptions?.brokeredCredentialSourceIDs;
serialized = this.serializeWithCredentialSources( const injectedApplicationCredentialSourceIDs =
snapshot?.adapterOptions?.injectedApplicationCredentialSourceIDs;
if (brokeredCredentialSourceIDs)
serialized = this.serializeWithBrokeredCredentialSources(
snapshot, snapshot,
credentialSourceIDs brokeredCredentialSourceIDs
);
if (injectedApplicationCredentialSourceIDs)
serialized = this.serializeWithInjectedApplicationCredentialSources(
snapshot,
injectedApplicationCredentialSourceIDs
); );
return serialized; return serialized;
} }
@@ -48,13 +57,33 @@ export default class TargetSerializer extends ApplicationSerializer {
* Returns a payload containing only version and an array of passed IDs, * Returns a payload containing only version and an array of passed IDs,
* rather than existing instances on the model. * rather than existing instances on the model.
* @param {Snapshot} snapshot * @param {Snapshot} snapshot
* @param {[string]} credentialSourceIDs * @param {[string]} brokered_credential_source_ids
* @return {object} * @return {object}
*/ */
serializeWithCredentialSources(snapshot, credentialSourceIDs) { serializeWithBrokeredCredentialSources(
snapshot,
brokered_credential_source_ids
) {
return { return {
version: snapshot.attr('version'), version: snapshot.attr('version'),
application_credential_source_ids: credentialSourceIDs, brokered_credential_source_ids,
};
}
/**
* Returns a payload containing only version and an array of passed IDs,
* rather than existing instances on the model.
* @param {Snapshot} snapshot
* @param {[string]} injected_application_credential_source_ids
* @return {object}
*/
serializeWithInjectedApplicationCredentialSources(
snapshot,
injected_application_credential_source_ids
) {
return {
version: snapshot.attr('version'),
injected_application_credential_source_ids,
}; };
} }
} }
+37
View File
@@ -0,0 +1,37 @@
import ApplicationSerializer from './application';
export default class WorkerSerializer extends ApplicationSerializer {
// =methods
/**
* If `adapterOptions.workerGeneratedAuthToken` is set,
* then the payload is serialized via `serializedWithGeneratedToken`.
* @override
* @param {Snapshot} snapshot
* @return {object}
*/
serialize(snapshot) {
let serialized = super.serialize(...arguments);
const workerGeneratedAuthToken =
snapshot?.adapterOptions?.workerGeneratedAuthToken;
if (workerGeneratedAuthToken)
serialized = this.serializeWithGeneratedToken(
snapshot,
workerGeneratedAuthToken
);
return serialized;
}
/**
* Returns a payload with `worker_generated_auth_token` serialized.
* @param {Snapshot} snapshot
* @param {[string]} worker_generated_auth_token
* @return {object}
*/
serializeWithGeneratedToken(snapshot, workerGeneratedAuthToken) {
return {
scope_id: snapshot.attr('scope').scope_id,
worker_generated_auth_token: workerGeneratedAuthToken,
};
}
}
@@ -0,0 +1,16 @@
import Transform from '@ember-data/serializer/transform';
export default class HostSourceIdArrayTransform extends Transform {
deserialize(serialized) {
const stringValues = serialized || [];
return stringValues.map(({ id: host_source_id, ...obj }) => ({
host_source_id,
...obj,
}));
}
serialize(deserialized) {
const strings = deserialized || [];
return strings.map(({ host_source_id: id, ...obj }) => ({ id, ...obj }));
}
}
@@ -0,0 +1,21 @@
import Transform from '@ember-data/serializer/transform';
export default class PrincipalArrayTransform extends Transform {
deserialize(serialized) {
const stringValues = serialized || [];
return stringValues.map(({ id: principal_id, scope_id, type }) => ({
principal_id,
scope_id,
type,
}));
}
serialize(deserialized) {
const strings = deserialized || [];
return strings.map(({ principal_id: id, scope_id, type }) => ({
id,
scope_id,
type,
}));
}
}
@@ -0,0 +1,13 @@
import Transform from '@ember-data/serializer/transform';
export default class StringArrayTransform extends Transform {
deserialize(serialized) {
const stringValues = serialized || [];
return stringValues.map((value) => ({ value }));
}
serialize(deserialized) {
const strings = deserialized || [];
return strings.map(({ value }) => value);
}
}
@@ -0,0 +1 @@
export { default } from 'api/abilities/credential-library';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/abilities/credential';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/abilities/worker';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/models/credential';
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-account-attributes';
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-credential-library-attributes';
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-credential-store-attributes';
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-host-source';
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-managed-group-attributes';
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-principal';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-scope';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/models/worker';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/serializers/credential';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-account-attributes';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-credential-library-attributes';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-credential-store-attributes';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-host-source';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-managed-group-attributes';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-principal';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/serializers/worker';
@@ -0,0 +1 @@
export { default } from 'api/transforms/host-source-id-array';
@@ -0,0 +1 @@
export { default } from 'api/transforms/principal-array';
@@ -0,0 +1 @@
export { default } from 'api/transforms/string-array';
+102 -55
View File
@@ -1,5 +1,6 @@
import config from '../config/environment'; import config from '../config/environment';
import { authHandler, deauthHandler } from './route-handlers/auth'; import { authHandler, deauthHandler } from './route-handlers/auth';
import { targetHandler } from './route-handlers/target';
import { pickRandomStatusString } from './factories/session'; import { pickRandomStatusString } from './factories/session';
import { Response } from 'miragejs'; import { Response } from 'miragejs';
import initializeMockIPC from './scenarios/ipc'; import initializeMockIPC from './scenarios/ipc';
@@ -57,8 +58,23 @@ export default function () {
this.get( this.get(
'/auth-methods', '/auth-methods',
({ authMethods }, { queryParams: { scope_id: scopeId, filter } }) => { ({ authMethods }, { queryParams: { scope_id, recursive, filter } }) => {
const resultSet = authMethods.where({ scopeId }); let resultSet;
if (recursive && scope_id === 'global') {
resultSet = authMethods.all();
} else if (recursive) {
resultSet = authMethods.where((authMethod) => {
const authMethodModel = authMethods.find(authMethod.id);
return (
authMethod.scopeId === scope_id ||
authMethodModel?.scope?.scope?.id === scope_id
);
});
} else {
resultSet = authMethods.where(
(authMethod) => authMethod.scopeId === scope_id
);
}
return resultSet.filter(makeBooleanFilter(filter)); return resultSet.filter(makeBooleanFilter(filter));
} }
); );
@@ -123,12 +139,29 @@ export default function () {
// Authenticate + auth methods custom routes // Authenticate + auth methods custom routes
this.post('/auth-methods/:id_method', authHandler); this.post('/auth-methods/:id_method', authHandler);
// Deauthenticate route // Deauthenticate route
this.post('/scopes/:id_method', deauthHandler); this.delete('/auth-tokens/:id', deauthHandler);
// IAM : Users // IAM : Users
this.get('/users', ({ users }, { queryParams: { scope_id: scopeId } }) => { this.get(
return users.where({ scopeId }); '/users',
}); ({ users }, { queryParams: { scope_id, recursive, filter } }) => {
let resultSet;
if (recursive && scope_id === 'global') {
resultSet = users.all();
} else if (recursive) {
resultSet = users.where((user) => {
const userModel = users.find(user.id);
return (
user.scopeId === scope_id ||
userModel?.scope?.scope?.id === scope_id
);
});
} else {
resultSet = users.where((user) => user.scopeId === scope_id);
}
return resultSet.filter(makeBooleanFilter(filter));
}
);
this.post('/users'); this.post('/users');
this.get('/users/:id'); this.get('/users/:id');
this.patch('/users/:id'); this.patch('/users/:id');
@@ -160,9 +193,26 @@ export default function () {
}); });
// IAM: Groups // IAM: Groups
this.get('/groups', ({ groups }, { queryParams: { scope_id: scopeId } }) => { this.get(
return groups.where({ scopeId }); '/groups',
}); ({ groups }, { queryParams: { scope_id, recursive, filter } }) => {
let resultSet;
if (recursive && scope_id === 'global') {
resultSet = groups.all();
} else if (recursive) {
resultSet = groups.where((group) => {
const groupModel = groups.find(group.id);
return (
group.scopeId === scope_id ||
groupModel?.scope?.scope?.id === scope_id
);
});
} else {
resultSet = groups.where((group) => group.scopeId === scope_id);
}
return resultSet.filter(makeBooleanFilter(filter));
}
);
this.post('/groups'); this.post('/groups');
this.get('/groups/:id'); this.get('/groups/:id');
this.patch('/groups/:id'); this.patch('/groups/:id');
@@ -386,52 +436,7 @@ export default function () {
this.get('/targets/:id'); this.get('/targets/:id');
this.patch('/targets/:id'); this.patch('/targets/:id');
this.del('/targets/:id'); this.del('/targets/:id');
this.post( this.post('/targets/:idMethod', targetHandler);
'/targets/:idMethod',
function ({ targets }, { params: { idMethod } }) {
const attrs = this.normalizedRequestAttrs();
const id = idMethod.split(':')[0];
const method = idMethod.split(':')[1];
const target = targets.find(id);
const updatedAttrs = {
version: attrs.version,
};
// If adding host sources, push them into the array
if (method === 'add-host-sources') {
updatedAttrs.hostSetIds = target.hostSetIds;
attrs.hostSourceIds.forEach((id) => {
if (!updatedAttrs.hostSetIds.includes(id)) {
updatedAttrs.hostSetIds.push(id);
}
});
}
// If deleting host sources, filter them out of the array
if (method === 'remove-host-sources') {
updatedAttrs.hostSetIds = target.hostSetIds;
updatedAttrs.hostSetIds = updatedAttrs.hostSetIds.filter((id) => {
return !attrs.hostSourceIds.includes(id);
});
}
// If adding credential sources, push them into the array
if (method === 'add-credential-sources') {
updatedAttrs.credentialLibraryIds = target.credentialLibraryIds;
attrs.applicationCredentialSourceIds.forEach((id) => {
if (!updatedAttrs.credentialLibraryIds.includes(id)) {
updatedAttrs.credentialLibraryIds.push(id);
}
});
}
// If deleting credential sources, filter them out of the array
if (method === 'remove-credential-sources') {
updatedAttrs.credentialLibraryIds = target.credentialLibraryIds;
updatedAttrs.credentialLibraryIds =
updatedAttrs.credentialLibraryIds.filter((id) => {
return !attrs.applicationCredentialSourceIds.includes(id);
});
}
return target.update(updatedAttrs);
}
);
// session // session
@@ -541,6 +546,26 @@ export default function () {
this.del('/credential-libraries/:id'); this.del('/credential-libraries/:id');
this.patch('/credential-libraries/:id'); this.patch('/credential-libraries/:id');
// credentials
this.get(
'/credentials',
(
{ credentials },
{ queryParams: { credential_store_id: credentialStoreId } }
) => credentials.where({ credentialStoreId })
);
this.get('/credentials/:id');
this.post('/credentials', function ({ credentialStores, credentials }) {
const attrs = this.normalizedRequestAttrs();
const credentialStore = credentialStores.find(attrs.credentialStoreId);
attrs.scopeId = credentialStore.scope.id;
return credentials.create(attrs);
});
this.del('/credentials/:id');
this.patch('/credentials/:id');
// managed-groups // managed-groups
this.get( this.get(
'/managed-groups', '/managed-groups',
@@ -553,6 +578,28 @@ export default function () {
this.patch('/managed-groups/:id'); this.patch('/managed-groups/:id');
this.del('/managed-groups/:id'); this.del('/managed-groups/:id');
// worker
this.get(
'/workers',
({ workers }, { queryParams: { scope_id: scopeId } }) => {
return workers.where({ scopeId });
}
);
this.get('/workers/:id');
this.del('/workers/:id');
this.patch('/workers/:id');
this.post('/workers:create:worker-led', ({ workers, scopes }) => {
const globalScope = scopes.find('global');
// This POST only takes in a token so we need to generate a random worker to return
const newWorker = this.create('worker', {
type: 'pki',
scope: globalScope,
});
return workers.create(newWorker.attrs);
});
/* Uncomment the following line and the Response import above /* Uncomment the following line and the Response import above
* Then change the response code to simulate error responses. * Then change the response code to simulate error responses.
* this.get('/scopes', () => new Response(505)); * this.get('/scopes', () => new Response(505));
+5 -5
View File
@@ -1,5 +1,5 @@
import factory from '../generated/factories/account'; import factory from '../generated/factories/account';
import { random, internet } from 'faker'; import { faker } from '@faker-js/faker';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
@@ -18,13 +18,13 @@ export default factory.extend({
attributes() { attributes() {
switch (this.type) { switch (this.type) {
case 'password': case 'password':
return { login_name: random.words() }; return { login_name: faker.random.words() };
case 'oidc': case 'oidc':
return { return {
issuer: internet.ip(), issuer: faker.internet.ip(),
subject: 'sub', subject: 'sub',
email: internet.email(), email: faker.internet.email(),
full_name: random.words(), full_name: faker.random.words(),
}; };
} }
}, },
@@ -12,6 +12,7 @@ export default factory.extend({
'read', 'read',
'update', 'update',
'delete', 'delete',
'authenticate',
], ],
authorized_collection_actions: () => { authorized_collection_actions: () => {
return { return {
@@ -1,5 +1,5 @@
import factory from '../generated/factories/credential-library'; import factory from '../generated/factories/credential-library';
import { random, system } from 'faker'; import { faker } from '@faker-js/faker';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
@@ -22,8 +22,8 @@ export default factory.extend({
case 'vault': case 'vault':
return { return {
http_method: 'GET', http_method: 'GET',
http_request_body: random.word(), http_request_body: faker.random.word(),
path: system.directoryPath(), path: faker.system.directoryPath(),
}; };
} }
}, },
+33 -14
View File
@@ -1,5 +1,5 @@
import factory from '../generated/factories/credential-store'; import factory from '../generated/factories/credential-store';
import { random, internet, datatype } from 'faker'; import { faker } from '@faker-js/faker';
import { trait } from 'ember-cli-mirage'; import { trait } from 'ember-cli-mirage';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
@@ -14,10 +14,18 @@ export default factory.extend({
'update', 'update',
'delete', 'delete',
], ],
authorized_collection_actions: () => { authorized_collection_actions() {
return { switch (this.type) {
'credential-libraries': ['create', 'list'], case 'vault':
}; return {
'credential-libraries': ['create', 'list'],
};
case 'static':
default:
return {
credentials: ['create', 'list'],
};
}
}, },
id: () => generateId('cs_'), id: () => generateId('cs_'),
type: (i) => types[i % types.length], type: (i) => types[i % types.length],
@@ -26,25 +34,36 @@ export default factory.extend({
switch (this.type) { switch (this.type) {
case 'vault': case 'vault':
return { return {
address: internet.ip(), address: faker.internet.ip(),
namespace: random.word(), namespace: faker.random.word(),
ca_cert: 'ca-cert-123', ca_cert: 'ca-cert-123',
tls_server_name: internet.domainName(), tls_server_name: faker.internet.domainName(),
tls_skip_verify: datatype.boolean(), tls_skip_verify: faker.datatype.boolean(),
token_hmac: 'token-hmac-abcde0987654321', token_hmac: 'token-hmac-abcde0987654321',
client_certificate: 'client-cert-123', client_certificate: 'client-cert-123',
client_certificate_key_hmac: 'client-cert-key-hmac-abcde0987654321', client_certificate_key_hmac: 'client-cert-key-hmac-abcde0987654321',
worker_filter: faker.random.words(),
}; };
} }
}, },
withAssociations: trait({ withAssociations: trait({
afterCreate(credentialStore, server) { afterCreate(credentialStore, server) {
const { scope } = credentialStore; const { scope, type } = credentialStore;
server.createList('credential-library', 2, { switch (type) {
scope, case 'vault':
credentialStore, server.createList('credential-library', 2, {
}); scope,
credentialStore,
});
break;
case 'static':
default:
server.createList('credential', 3, {
scope,
credentialStore,
});
}
}, },
}), }),
}); });
+32
View File
@@ -0,0 +1,32 @@
import factory from '../generated/factories/credential';
import { faker } from '@faker-js/faker';
import permissions from '../helpers/permissions';
import generatedId from '../helpers/id';
const types = ['username_password', 'ssh_private_key', 'json'];
export default factory.extend({
type: (i) => types[i % types.length],
id() {
switch (this.type) {
case 'ssh_private_key':
return generatedId('credspk_');
case 'username_password':
return generatedId('credup_');
case 'json':
return generatedId('credjson_');
}
},
authorized_actions: () =>
permissions.authorizedActionsFor('credential') || [
'no-op',
'read',
'update',
'delete',
],
attributes() {
return {
username: faker.random.word(),
};
},
});
+12 -12
View File
@@ -1,7 +1,7 @@
import factory from '../generated/factories/host-catalog'; import factory from '../generated/factories/host-catalog';
import { trait } from 'ember-cli-mirage'; import { trait } from 'ember-cli-mirage';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import { datatype, address, random } from 'faker'; import { faker } from '@faker-js/faker';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
const types = ['static', 'plugin']; const types = ['static', 'plugin'];
@@ -38,7 +38,7 @@ export default factory.extend({
return { return {
id: `plugin-id-${i}`, id: `plugin-id-${i}`,
name: pluginTypes[pluginTypeCounter++ % pluginTypes.length], name: pluginTypes[pluginTypeCounter++ % pluginTypes.length],
description: random.words(), description: faker.random.words(),
}; };
} }
}, },
@@ -47,15 +47,15 @@ export default factory.extend({
switch (this.plugin?.name) { switch (this.plugin?.name) {
case 'aws': case 'aws':
return { return {
disable_credential_rotation: datatype.boolean(), disable_credential_rotation: faker.datatype.boolean(),
region: address.state(), region: faker.address.state(),
}; };
case 'azure': case 'azure':
return { return {
disable_credential_rotation: datatype.boolean(), disable_credential_rotation: faker.datatype.boolean(),
tenant_id: datatype.hexaDecimal(6), tenant_id: faker.datatype.hexadecimal(6),
client_id: datatype.hexaDecimal(6), client_id: faker.datatype.hexadecimal(6),
subscription_id: datatype.hexaDecimal(8), subscription_id: faker.datatype.hexadecimal(8),
}; };
} }
}, },
@@ -64,13 +64,13 @@ export default factory.extend({
switch (this.plugin?.name) { switch (this.plugin?.name) {
case 'aws': case 'aws':
return { return {
access_key_id: datatype.hexaDecimal(8), access_key_id: faker.datatype.hexadecimal(8),
secret_access_key: datatype.string(12), secret_access_key: faker.datatype.string(12),
}; };
case 'azure': case 'azure':
return { return {
secret_id: datatype.hexaDecimal(6), secret_id: faker.datatype.hexadecimal(6),
secret_value: datatype.string(12), secret_value: faker.datatype.string(12),
}; };
} }
}, },
+17 -14
View File
@@ -1,6 +1,6 @@
import factory from '../generated/factories/host-set'; import factory from '../generated/factories/host-set';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import { datatype, internet, database } from 'faker'; import { faker } from '@faker-js/faker';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
export default factory.extend({ export default factory.extend({
@@ -22,34 +22,37 @@ export default factory.extend({
}, },
preferred_endpoints() { preferred_endpoints() {
if (this.type === 'plugin') { if (this.type === 'plugin') {
const enpointsAmount = datatype.number({ min: 1, max: 5 }); const enpointsAmount = faker.datatype.number({ min: 1, max: 5 });
let result = []; let result = [];
for (let i = 0; i < enpointsAmount; ++i) { for (let i = 0; i < enpointsAmount; ++i) {
result.push(internet.ip()); result.push(faker.internet.ip());
} }
return result; return result;
} }
}, },
sync_interval_seconds() { sync_interval_seconds() {
if (this.type === 'plugin') { if (this.type === 'plugin') {
return datatype.number(); return faker.datatype.number();
} }
}, },
// AWS specific
filters() { attributes() {
// AWS specific
if (this.plugin?.name === 'aws') { if (this.plugin?.name === 'aws') {
const filtersAmount = datatype.number({ min: 1, max: 5 }); const filtersAmount = faker.datatype.number({ min: 1, max: 5 });
let result = []; let filters = [];
for (let i = 0; i < filtersAmount; ++i) { for (let i = 0; i < filtersAmount; ++i) {
result.push(`${datatype.string(3)}=${datatype.string(8)}`); filters.push(`${faker.datatype.string(3)}=${faker.datatype.string(8)}`);
} }
return result; return {
filters,
};
} }
}, // Azure specific
// Azure specific
filter() {
if (this.plugin?.name === 'azure') { if (this.plugin?.name === 'azure') {
return `${database.column()}=${database.collation()}`; return {
filter: `${faker.database.column()}=${faker.database.collation()}`,
};
} }
}, },
}); });
+4 -4
View File
@@ -1,6 +1,6 @@
import factory from '../generated/factories/host'; import factory from '../generated/factories/host';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import { internet, datatype } from 'faker'; import { faker } from '@faker-js/faker';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
export default factory.extend({ export default factory.extend({
@@ -25,12 +25,12 @@ export default factory.extend({
const addressesAmount = Math.floor(Math.random() * 6) + 1; const addressesAmount = Math.floor(Math.random() * 6) + 1;
let result = []; let result = [];
for (let i = 0; i < addressesAmount; ++i) { for (let i = 0; i < addressesAmount; ++i) {
result.push(internet.ip()); result.push(faker.internet.ip());
} }
return result; return result;
}, },
external_id() { external_id() {
return datatype.uuid(); return faker.datatype.uuid();
}, },
// Only aws plugins have dns_names // Only aws plugins have dns_names
dns_names() { dns_names() {
@@ -38,7 +38,7 @@ export default factory.extend({
const dnsNamesAmount = Math.floor(Math.random() * 6) + 1; const dnsNamesAmount = Math.floor(Math.random() * 6) + 1;
let result = []; let result = [];
for (let i = 0; i < dnsNamesAmount; i++) { for (let i = 0; i < dnsNamesAmount; i++) {
result.push(internet.domainName()); result.push(faker.internet.domainName());
} }
return result; return result;
} }
+2 -2
View File
@@ -1,5 +1,5 @@
import factory from '../generated/factories/managed-group'; import factory from '../generated/factories/managed-group';
import { random } from 'faker'; import { faker } from '@faker-js/faker';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
@@ -22,7 +22,7 @@ export default factory.extend({
switch (this.type) { switch (this.type) {
case 'oidc': case 'oidc':
return { return {
filter: random.words(), filter: faker.random.words(),
}; };
} }
}, },
+9 -2
View File
@@ -14,8 +14,8 @@ export default factory.extend({
'delete', 'delete',
], ],
authorized_collection_actions: () => { authorized_collection_actions() {
return { const collectionActions = {
scopes: ['create', 'list'], scopes: ['create', 'list'],
users: ['create', 'list'], users: ['create', 'list'],
sessions: ['list'], sessions: ['list'],
@@ -26,6 +26,13 @@ export default factory.extend({
'auth-methods': ['create', 'list'], 'auth-methods': ['create', 'list'],
'host-catalogs': ['create', 'list'], 'host-catalogs': ['create', 'list'],
}; };
// Worker permissions only available on the global scope
if (this.type === 'global') {
collectionActions.workers = ['create:worker-led', 'list'];
}
return collectionActions;
}, },
id: () => generateId('s_'), id: () => generateId('s_'),
+3 -2
View File
@@ -1,11 +1,12 @@
import factory from '../generated/factories/session'; import factory from '../generated/factories/session';
import { trait } from 'ember-cli-mirage'; import { trait } from 'ember-cli-mirage';
import { random } from 'faker'; import { faker } from '@faker-js/faker';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
const statusStrings = ['pending', 'active', 'canceling', 'terminated']; const statusStrings = ['pending', 'active', 'canceling', 'terminated'];
export const pickRandomStatusString = () => random.arrayElement(statusStrings); export const pickRandomStatusString = () =>
faker.helpers.arrayElement(statusStrings);
export default factory.extend({ export default factory.extend({
id: () => generateId('ss_'), id: () => generateId('ss_'),
+22 -8
View File
@@ -1,6 +1,6 @@
import factory from '../generated/factories/target'; import factory from '../generated/factories/target';
import { trait } from 'ember-cli-mirage'; import { trait } from 'ember-cli-mirage';
import { random, datatype } from 'faker'; import { faker } from '@faker-js/faker';
import permissions from '../helpers/permissions'; import permissions from '../helpers/permissions';
import generateId from '../helpers/id'; import generateId from '../helpers/id';
@@ -27,8 +27,9 @@ export default factory.extend({
/** /**
* -1 means "unlimited" and we want to generate these on occasion. * -1 means "unlimited" and we want to generate these on occasion.
*/ */
session_connection_limit: () => random.arrayElement([-1, datatype.number()]), session_connection_limit: () =>
worker_filter: (i) => (i % 2 === 0 ? random.words() : null), faker.helpers.arrayElement([-1, faker.datatype.number()]),
worker_filter: (i) => (i % 2 === 0 ? faker.random.words() : null),
type: (i) => types[i % types.length], type: (i) => types[i % types.length],
/** /**
* Generates attributes fields by type. * Generates attributes fields by type.
@@ -37,7 +38,7 @@ export default factory.extend({
if (target.type === 'tcp' || target.type === 'ssh') { if (target.type === 'tcp' || target.type === 'ssh') {
target.update({ target.update({
attributes: { attributes: {
default_port: datatype.number(), default_port: faker.datatype.number(),
}, },
}); });
} }
@@ -48,7 +49,9 @@ export default factory.extend({
*/ */
withAssociations: trait({ withAssociations: trait({
afterCreate(target, server) { afterCreate(target, server) {
let randomlySelectedHostSets, randomlySelectedCredentialLibraries; let randomlySelectedHostSets,
randomlySelectedCredentialLibraries,
randomlySelectedCredentials;
randomlySelectedHostSets = server.schema.hostSets randomlySelectedHostSets = server.schema.hostSets
// BLERG: fun fact, for no reason at all, the element passed // BLERG: fun fact, for no reason at all, the element passed
// into a where function is not a full model instance, as you might // into a where function is not a full model instance, as you might
@@ -62,11 +65,22 @@ export default factory.extend({
.where( .where(
(credentialLibrary) => credentialLibrary.scopeId === target.scope.id (credentialLibrary) => credentialLibrary.scopeId === target.scope.id
) )
.models.filter(() => randomBoolean()); .models.filter(() => randomBoolean())
.map((cred) => cred.id);
randomlySelectedCredentials = server.schema.credentials
.where((credential) => credential.scopeId === target.scope.id)
.models.filter(() => randomBoolean())
.map((cred) => cred.id);
target.update({ target.update({
hostSets: randomlySelectedHostSets, hostSets: randomlySelectedHostSets,
credentialLibraries: randomlySelectedCredentialLibraries, brokeredCredentialSourceIds: [
...randomlySelectedCredentialLibraries,
...randomlySelectedCredentials,
],
injectedApplicationCredentialSourceIds: [
...randomlySelectedCredentialLibraries,
...randomlySelectedCredentials,
],
}); });
}, },
}), }),
+44
View File
@@ -0,0 +1,44 @@
import factory from '../generated/factories/worker';
import permissions from '../helpers/permissions';
import generateId from '../helpers/id';
import { faker } from '@faker-js/faker';
const types = ['pki', 'kms'];
export default factory.extend({
id: () => generateId('w_'),
authorized_actions: () =>
permissions.authorizedActionsFor('worker') || [
'no-op',
'read',
'update',
'delete',
],
type: (i) => types[i % types.length],
canonical_tags: (i) => {
if (i % 3 === 0) {
return { os: ['ubuntu'] };
}
if (i % 2 === 0) {
return {
type: [faker.random.word(), faker.random.word()],
os: ['ubuntu'],
env: ['dev', 'local'],
};
}
return undefined;
},
config_tags: (i) => {
if (i % 3 === 0) {
return { os: ['ubuntu'] };
}
if (i % 2 === 0) {
return {
type: [faker.random.word(), faker.random.word()],
os: ['ubuntu'],
env: ['dev', 'local'],
};
}
return undefined;
},
});
@@ -1,14 +1,12 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { date, datatype } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedAccountFactory * GeneratedAccountFactory
*/ */
export default Factory.extend({ export default Factory.extend({
type: 'password', type: 'password',
// name: () => random.words(), created_time: () => faker.date.recent(),
// description: () => random.words(), updated_time: () => faker.date.recent(),
created_time: () => date.recent(), version: () => faker.datatype.number(),
updated_time: () => date.recent(),
version: () => datatype.number(),
}); });
@@ -1,16 +1,16 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date, datatype } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedAuthMethodModelFactory * GeneratedAuthMethodModelFactory
*/ */
export default Factory.extend({ export default Factory.extend({
type: 'password', type: 'password',
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
disabled: () => datatype.boolean(), disabled: () => faker.datatype.boolean(),
attributes: function () { attributes: function () {
let attrs; let attrs;
@@ -1,12 +1,12 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedCredentialLibraryModelFactory * GeneratedCredentialLibraryModelFactory
*/ */
export default Factory.extend({ export default Factory.extend({
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
}); });
@@ -1,12 +1,12 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedCredentialStoreModelFactory * GeneratedCredentialStoreModelFactory
*/ */
export default Factory.extend({ export default Factory.extend({
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
}); });
@@ -0,0 +1,13 @@
import { Factory } from 'ember-cli-mirage';
import { faker } from '@faker-js/faker';
/**
* GeneratedCredentialModelFactory
*/
export default Factory.extend({
name: () => faker.random.words(),
description: () => faker.random.words(),
created_time: () => faker.date.recent(),
updated_time: () => faker.date.recent(),
version: () => faker.datatype.number(),
});
@@ -1,14 +1,14 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date, datatype } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedGroupModelFactory * GeneratedGroupModelFactory
* Group contains all fields related to a Group resource * Group contains all fields related to a Group resource
*/ */
export default Factory.extend({ export default Factory.extend({
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
disabled: () => datatype.boolean(), disabled: () => faker.datatype.boolean(),
}); });
@@ -1,14 +1,14 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date, datatype } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedHostCatalogModelFactory * GeneratedHostCatalogModelFactory
*/ */
export default Factory.extend({ export default Factory.extend({
type: 'static', type: 'static',
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
disabled: () => datatype.boolean(), disabled: () => faker.datatype.boolean(),
}); });
@@ -1,15 +1,15 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date, datatype } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedHostSetModelFactory * GeneratedHostSetModelFactory
*/ */
export default Factory.extend({ export default Factory.extend({
type: 'static', type: 'static',
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
version: () => datatype.number(), version: () => faker.datatype.number(),
size: () => datatype.number(), size: () => faker.datatype.number(),
}); });
@@ -1,17 +1,17 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date, datatype, internet } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedHostModelFactory * GeneratedHostModelFactory
*/ */
export default Factory.extend({ export default Factory.extend({
type: 'static', type: 'static',
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
version: () => datatype.number(), version: () => faker.datatype.number(),
attributes: () => { attributes: () => {
return { address: internet.ipv6() }; return { address: faker.internet.ipv6() };
}, },
}); });
@@ -1,14 +1,14 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date, datatype } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedManagedGroupFactory * GeneratedManagedGroupFactory
* A managed group is a resource that represents a collection of accounts. * A managed group is a resource that represents a collection of accounts.
*/ */
export default Factory.extend({ export default Factory.extend({
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
version: () => datatype.number(), version: () => faker.datatype.number(),
}); });
+5 -5
View File
@@ -1,13 +1,13 @@
import { Factory } from 'ember-cli-mirage'; import { Factory } from 'ember-cli-mirage';
import { random, date } from 'faker'; import { faker } from '@faker-js/faker';
/** /**
* GeneratedOrgModelFactory * GeneratedOrgModelFactory
* *
*/ */
export default Factory.extend({ export default Factory.extend({
name: () => random.words(), name: () => faker.random.words(),
description: () => random.words(), description: () => faker.random.words(),
created_time: () => date.recent(), created_time: () => faker.date.recent(),
updated_time: () => date.recent(), updated_time: () => faker.date.recent(),
}); });
Loaded 100 of 829 files, more files were not shown because too many files have changed in this diff. Show more