@synopackageland/cli 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +613 -0
- package/README.md +81 -78
- package/dist/add.js +39 -16
- package/dist/authorization-sdk.d.ts +7 -0
- package/dist/authorization-sdk.js +7 -0
- package/dist/build-spk/delegate-scope.d.ts +6 -0
- package/dist/build-spk/delegate-scope.js +34 -0
- package/dist/build-spk/dsm-arch.d.ts +7 -1
- package/dist/build-spk/dsm-arch.js +24 -28
- package/dist/build-spk/dsm-platforms.json +39 -0
- package/dist/build-spk/dsm-version.d.ts +11 -0
- package/dist/build-spk/dsm-version.js +17 -0
- package/dist/build-spk/gateway.d.ts +1 -1
- package/dist/build-spk/gateway.js +2 -2
- package/dist/build-spk/generator.js +30 -5
- package/dist/build-spk/notices.js +4 -1
- package/dist/build-spk/resource-worker.js +3 -0
- package/dist/build-spk/wizard-messages.d.ts +66 -0
- package/dist/build-spk/wizard-messages.js +75 -9
- package/dist/cli.js +30 -18
- package/dist/contract/schema-validate.js +8 -0
- package/dist/contract/validate.js +30 -0
- package/dist/deploy/deploy.d.ts +1 -1
- package/dist/deploy/deploy.js +8 -0
- package/dist/deploy/plan.js +1 -1
- package/dist/deploy/spk-version.js +1 -1
- package/dist/error-registry.js +46 -13
- package/dist/host/dsm-client.d.ts +8 -4
- package/dist/host/dsm-client.js +10 -4
- package/dist/host/types.d.ts +2 -1
- package/dist/info.js +18 -2
- package/dist/init.d.ts +3 -0
- package/dist/init.js +49 -18
- package/dist/package-metadata.d.ts +21 -0
- package/dist/package-metadata.js +101 -0
- package/dist/portal/alias.d.ts +25 -0
- package/dist/portal/alias.js +48 -0
- package/dist/portal/package.d.ts +33 -0
- package/dist/portal/package.js +116 -0
- package/dist/runtime/delegate-contract.d.ts +79 -0
- package/dist/runtime/delegate-contract.js +27 -0
- package/dist/runtime/executor-build.d.ts +1 -1
- package/dist/runtime/executor-build.js +5 -4
- package/dist/runtime/executor-inspect.d.ts +3 -0
- package/dist/runtime/executor-inspect.js +11 -5
- package/dist/runtime/executor-policy.d.ts +12 -0
- package/dist/runtime/executor-policy.js +43 -3
- package/dist/runtime/executor-scope-task.d.ts +4 -0
- package/dist/runtime/executor-scope-task.js +21 -0
- package/dist/runtime/executor-tasks.d.ts +2 -1
- package/dist/runtime/executor-tasks.js +4 -4
- package/dist/skill.js +1 -0
- package/dist/standalone/api-permissions.d.ts +10 -0
- package/dist/standalone/api-permissions.js +19 -2
- package/dist/standalone/background.d.ts +16 -0
- package/dist/standalone/background.js +69 -2
- package/dist/standalone/binary.d.ts +1 -1
- package/dist/standalone/binary.js +22 -8
- package/dist/standalone/build.d.ts +1 -1
- package/dist/standalone/build.js +38 -8
- package/dist/standalone/daemon.d.ts +1 -1
- package/dist/standalone/daemon.js +2 -1
- package/dist/standalone/dsm-window.d.ts +3 -1
- package/dist/standalone/dsm-window.js +72 -15
- package/dist/standalone/inspect-spk.d.ts +9 -1
- package/dist/standalone/inspect-spk.js +119 -26
- package/dist/standalone/lifecycle.js +86 -8
- package/dist/standalone/manifest.d.ts +13 -0
- package/dist/standalone/manifest.js +57 -8
- package/dist/standalone/native-authorization-window.d.ts +2 -0
- package/dist/standalone/native-authorization-window.js +30 -0
- package/dist/standalone/native-layout.d.ts +82 -0
- package/dist/standalone/native-layout.js +377 -0
- package/dist/standalone/native-root-window.d.ts +26 -0
- package/dist/standalone/native-root-window.js +282 -0
- package/dist/standalone/portal-window.d.ts +21 -0
- package/dist/standalone/portal-window.js +155 -0
- package/dist/standalone/portal.d.ts +4 -0
- package/dist/standalone/portal.js +4 -0
- package/dist/standalone/resource.d.ts +5 -3
- package/dist/standalone/resource.js +6 -3
- package/dist/standalone/root-window.js +62 -15
- package/dist/standalone/spk.d.ts +1 -1
- package/dist/standalone/spk.js +25 -7
- package/dist/templates/_daemon/main_test.go +61 -8
- package/dist/templates/_executor/README.md +127 -16
- package/dist/templates/_executor/anchor.go +146 -0
- package/dist/templates/_executor/anchor_test.go +126 -0
- package/dist/templates/_executor/apppriv_review_test.go +1 -1
- package/dist/templates/_executor/cancel_contract_test.go +236 -0
- package/dist/templates/_executor/copy.go +64 -0
- package/dist/templates/_executor/copy_test.go +88 -0
- package/dist/templates/_executor/dsm.go +23 -10
- package/dist/templates/_executor/dsm_test.go +95 -1
- package/dist/templates/_executor/executor.go +260 -49
- package/dist/templates/_executor/executor_test.go +36 -6
- package/dist/templates/_executor/identity.go +27 -1
- package/dist/templates/_executor/identity_kernel_linux_test.go +60 -0
- package/dist/templates/_executor/identity_linux.go +82 -0
- package/dist/templates/_executor/identity_security_test.go +43 -0
- package/dist/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
- package/dist/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
- package/dist/templates/_executor/internal/taskscript/boot.sh +9 -9
- package/dist/templates/_executor/internal/taskscript/cmd/main.go +2 -2
- package/dist/templates/_executor/internal/taskscript/control.sh +15 -10
- package/dist/templates/_executor/internal/taskscript/tasks.go +5 -3
- package/dist/templates/_executor/lifecycle_test.go +11 -0
- package/dist/templates/_executor/link_linux.go +28 -0
- package/dist/templates/_executor/long_running_test.go +530 -0
- package/dist/templates/_executor/main.go +72 -20
- package/dist/templates/_executor/move_linux.go +490 -0
- package/dist/templates/_executor/move_linux_test.go +460 -0
- package/dist/templates/_executor/move_validation.go +46 -0
- package/dist/templates/_executor/move_validation_test.go +187 -0
- package/dist/templates/_executor/operations.go +926 -0
- package/dist/templates/_executor/platform_linux.go +24 -173
- package/dist/templates/_executor/platform_linux_test.go +9 -65
- package/dist/templates/_executor/platform_other.go +30 -4
- package/dist/templates/_executor/process.go +3 -0
- package/dist/templates/_executor/records.go +242 -0
- package/dist/templates/_executor/scope_cancel_contract_test.go +91 -0
- package/dist/templates/_executor/scope_client.go +37 -0
- package/dist/templates/_executor/scope_contract.go +12 -0
- package/dist/templates/_executor/selected_scope.go +146 -0
- package/dist/templates/_executor/selected_scope_test.go +186 -0
- package/dist/templates/_executor/status_disabled_test.go +33 -0
- package/dist/templates/_executor/store.go +4 -3
- package/dist/templates/_executor/supervise.go +109 -0
- package/dist/templates/_executor/supervise_test.go +130 -0
- package/dist/templates/_executor/task_race_review_test.go +1 -1
- package/dist/templates/_executor/tasks.go +7 -8
- package/dist/templates/_executor/tasks_review_test.go +1 -1
- package/dist/templates/_executor/tasks_test.go +4 -4
- package/dist/templates/_executor/watch.go +8 -0
- package/dist/templates/_executor/watch_test.go +23 -2
- package/dist/templates/_executor/write_review_linux_test.go +4 -12
- package/dist/templates/_shared/AGENTS.md +129 -0
- package/dist/templates/binary/dsm-package.yaml +24 -0
- package/dist/templates/binary/i18n/messages/de.json +4 -0
- package/dist/templates/binary/i18n/messages/en.json +4 -0
- package/dist/templates/binary/i18n/messages/es.json +4 -0
- package/dist/templates/binary/i18n/messages/fr.json +4 -0
- package/dist/templates/binary/i18n/messages/it.json +4 -0
- package/dist/templates/binary/i18n/messages/ja.json +4 -0
- package/dist/templates/binary/i18n/messages/ko.json +4 -0
- package/dist/templates/binary/i18n/messages/zh-CN.json +4 -0
- package/dist/templates/binary/i18n/messages/zh-TW.json +4 -0
- package/dist/templates/binary/ui/app.js +19 -4
- package/dist/templates/native-authorization/AuthorizationGate.vue +91 -0
- package/dist/templates/native-authorization/i18n/de.json +37 -0
- package/dist/templates/native-authorization/i18n/en.json +37 -0
- package/dist/templates/native-authorization/i18n/es.json +37 -0
- package/dist/templates/native-authorization/i18n/fr.json +37 -0
- package/dist/templates/native-authorization/i18n/index.ts +15 -0
- package/dist/templates/native-authorization/i18n/it.json +37 -0
- package/dist/templates/native-authorization/i18n/ja.json +37 -0
- package/dist/templates/native-authorization/i18n/ko.json +37 -0
- package/dist/templates/native-authorization/i18n/zh-CN.json +37 -0
- package/dist/templates/native-authorization/i18n/zh-TW.json +37 -0
- package/dist/templates/native-go/README.md +43 -10
- package/dist/templates/native-go/backend/cmd/app/main.go +27 -7
- package/dist/templates/native-go/backend/internal/api/entry_test.go +47 -0
- package/dist/templates/native-go/backend/internal/api/permissions_test.go +3 -3
- package/dist/templates/native-go/backend/internal/api/registry.go +11 -0
- package/dist/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
- package/dist/templates/native-go/backend/internal/api/server.go +18 -5
- package/dist/templates/native-go/backend/internal/app/delegate_config.go +57 -0
- package/dist/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
- package/dist/templates/native-go/backend/internal/app/portal.go +30 -0
- package/dist/templates/native-go/backend/internal/app/portal_test.go +55 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +8 -2
- package/dist/templates/native-go/backend/internal/background/runner.go +1 -1
- package/dist/templates/native-go/backend/internal/background/store.go +16 -14
- package/dist/templates/native-go/backend/internal/dsm/admin.go +8 -2
- package/dist/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
- package/dist/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
- package/dist/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
- package/dist/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
- package/dist/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
- package/dist/templates/native-go/backend/internal/dsm/entry.go +177 -0
- package/dist/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
- package/dist/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
- package/dist/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
- package/dist/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
- package/dist/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
- package/dist/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
- package/dist/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
- package/dist/templates/native-go/backend/internal/filestation/service.go +1 -1
- package/dist/templates/native-go/backend/internal/portal/portal.go +138 -0
- package/dist/templates/native-go/backend/internal/portal/portal_test.go +89 -0
- package/dist/templates/native-go/dsm-package.yaml +20 -1
- package/dist/templates/native-go/i18n/glossary.json +2 -1
- package/dist/templates/native-go/i18n/messages/de.json +1 -0
- package/dist/templates/native-go/i18n/messages/en.json +1 -0
- package/dist/templates/native-go/i18n/messages/es.json +1 -0
- package/dist/templates/native-go/i18n/messages/fr.json +1 -0
- package/dist/templates/native-go/i18n/messages/it.json +1 -0
- package/dist/templates/native-go/i18n/messages/ja.json +1 -0
- package/dist/templates/native-go/i18n/messages/ko.json +1 -0
- package/dist/templates/native-go/i18n/messages/zh-CN.json +1 -0
- package/dist/templates/native-go/i18n/messages/zh-TW.json +1 -0
- package/dist/templates/native-go/ui/app.css +10 -0
- package/dist/templates/native-go/ui/app.js +11 -1
- package/dist/templates/native-go-delegate/DELEGATE.md +126 -5
- package/dist/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
- package/dist/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
- package/dist/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
- package/dist/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
- package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
- package/dist/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
- package/dist/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
- package/dist/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
- package/dist/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
- package/dist/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
- package/dist/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
- package/dist/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
- package/dist/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
- package/dist/templates/native-go-delegate/test.sh +1 -0
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
- package/dist/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
- package/dist/templates/native-go-vue/README.md +4 -0
- package/dist/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/dist/templates/native-go-vue/frontend/package.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/App.vue +18 -13
- package/dist/templates/native-go-vue/frontend/src/context.ts +31 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +52 -8
- package/dist/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
- package/dist/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +4 -2
- package/dist/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/de.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/en.json +12 -2
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/es.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/it.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +15 -5
- package/dist/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
- package/dist/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n.ts +13 -0
- package/dist/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
- package/dist/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
- package/dist/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
- package/dist/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
- package/dist/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
- package/dist/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
- package/dist/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
- package/dist/validate.js +2 -1
- package/package.json +12 -2
- package/schema/package-metadata.schema.json +101 -0
- package/schema/synology-app.schema.json +112 -0
- package/skills/SKILL.md +109 -3
- package/skills/reference/create.md +101 -2
- package/skills/reference/deploy.md +2 -2
- package/skills/reference/files.md +113 -2
- package/skills/reference/identity.md +70 -1
- package/skills/reference/portal.md +17 -0
- package/skills/reference/ui-vue.md +12 -0
- package/templates/_daemon/main_test.go +61 -8
- package/templates/_executor/README.md +127 -16
- package/templates/_executor/anchor.go +146 -0
- package/templates/_executor/anchor_test.go +126 -0
- package/templates/_executor/apppriv_review_test.go +1 -1
- package/templates/_executor/cancel_contract_test.go +236 -0
- package/templates/_executor/copy.go +64 -0
- package/templates/_executor/copy_test.go +88 -0
- package/templates/_executor/dsm.go +23 -10
- package/templates/_executor/dsm_test.go +95 -1
- package/templates/_executor/executor.go +260 -49
- package/templates/_executor/executor_test.go +36 -6
- package/templates/_executor/identity.go +27 -1
- package/templates/_executor/identity_kernel_linux_test.go +60 -0
- package/templates/_executor/identity_linux.go +82 -0
- package/templates/_executor/identity_security_test.go +43 -0
- package/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
- package/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
- package/templates/_executor/internal/taskscript/boot.sh +9 -9
- package/templates/_executor/internal/taskscript/cmd/main.go +2 -2
- package/templates/_executor/internal/taskscript/control.sh +15 -10
- package/templates/_executor/internal/taskscript/tasks.go +5 -3
- package/templates/_executor/lifecycle_test.go +11 -0
- package/templates/_executor/link_linux.go +28 -0
- package/templates/_executor/long_running_test.go +530 -0
- package/templates/_executor/main.go +72 -20
- package/templates/_executor/move_linux.go +490 -0
- package/templates/_executor/move_linux_test.go +460 -0
- package/templates/_executor/move_validation.go +46 -0
- package/templates/_executor/move_validation_test.go +187 -0
- package/templates/_executor/operations.go +926 -0
- package/templates/_executor/platform_linux.go +24 -173
- package/templates/_executor/platform_linux_test.go +9 -65
- package/templates/_executor/platform_other.go +30 -4
- package/templates/_executor/process.go +3 -0
- package/templates/_executor/records.go +242 -0
- package/templates/_executor/scope_cancel_contract_test.go +91 -0
- package/templates/_executor/scope_client.go +37 -0
- package/templates/_executor/scope_contract.go +12 -0
- package/templates/_executor/selected_scope.go +146 -0
- package/templates/_executor/selected_scope_test.go +186 -0
- package/templates/_executor/status_disabled_test.go +33 -0
- package/templates/_executor/store.go +4 -3
- package/templates/_executor/supervise.go +109 -0
- package/templates/_executor/supervise_test.go +130 -0
- package/templates/_executor/task_race_review_test.go +1 -1
- package/templates/_executor/tasks.go +7 -8
- package/templates/_executor/tasks_review_test.go +1 -1
- package/templates/_executor/tasks_test.go +4 -4
- package/templates/_executor/watch.go +8 -0
- package/templates/_executor/watch_test.go +23 -2
- package/templates/_executor/write_review_linux_test.go +4 -12
- package/templates/_shared/AGENTS.md +129 -0
- package/templates/binary/dsm-package.yaml +24 -0
- package/templates/binary/i18n/messages/de.json +4 -0
- package/templates/binary/i18n/messages/en.json +4 -0
- package/templates/binary/i18n/messages/es.json +4 -0
- package/templates/binary/i18n/messages/fr.json +4 -0
- package/templates/binary/i18n/messages/it.json +4 -0
- package/templates/binary/i18n/messages/ja.json +4 -0
- package/templates/binary/i18n/messages/ko.json +4 -0
- package/templates/binary/i18n/messages/zh-CN.json +4 -0
- package/templates/binary/i18n/messages/zh-TW.json +4 -0
- package/templates/binary/ui/app.js +19 -4
- package/templates/native-authorization/AuthorizationGate.vue +91 -0
- package/templates/native-authorization/i18n/de.json +37 -0
- package/templates/native-authorization/i18n/en.json +37 -0
- package/templates/native-authorization/i18n/es.json +37 -0
- package/templates/native-authorization/i18n/fr.json +37 -0
- package/templates/native-authorization/i18n/index.ts +15 -0
- package/templates/native-authorization/i18n/it.json +37 -0
- package/templates/native-authorization/i18n/ja.json +37 -0
- package/templates/native-authorization/i18n/ko.json +37 -0
- package/templates/native-authorization/i18n/zh-CN.json +37 -0
- package/templates/native-authorization/i18n/zh-TW.json +37 -0
- package/templates/native-go/README.md +43 -10
- package/templates/native-go/backend/cmd/app/main.go +27 -7
- package/templates/native-go/backend/internal/api/entry_test.go +47 -0
- package/templates/native-go/backend/internal/api/permissions_test.go +3 -3
- package/templates/native-go/backend/internal/api/registry.go +11 -0
- package/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
- package/templates/native-go/backend/internal/api/server.go +18 -5
- package/templates/native-go/backend/internal/app/delegate_config.go +57 -0
- package/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
- package/templates/native-go/backend/internal/app/portal.go +30 -0
- package/templates/native-go/backend/internal/app/portal_test.go +55 -0
- package/templates/native-go/backend/internal/app/routes.go +8 -2
- package/templates/native-go/backend/internal/background/runner.go +1 -1
- package/templates/native-go/backend/internal/background/store.go +16 -14
- package/templates/native-go/backend/internal/dsm/admin.go +8 -2
- package/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
- package/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
- package/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
- package/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
- package/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
- package/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
- package/templates/native-go/backend/internal/dsm/entry.go +177 -0
- package/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
- package/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
- package/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
- package/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
- package/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
- package/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
- package/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
- package/templates/native-go/backend/internal/filestation/service.go +1 -1
- package/templates/native-go/backend/internal/portal/portal.go +138 -0
- package/templates/native-go/backend/internal/portal/portal_test.go +89 -0
- package/templates/native-go/dsm-package.yaml +20 -1
- package/templates/native-go/i18n/glossary.json +2 -1
- package/templates/native-go/i18n/messages/de.json +1 -0
- package/templates/native-go/i18n/messages/en.json +1 -0
- package/templates/native-go/i18n/messages/es.json +1 -0
- package/templates/native-go/i18n/messages/fr.json +1 -0
- package/templates/native-go/i18n/messages/it.json +1 -0
- package/templates/native-go/i18n/messages/ja.json +1 -0
- package/templates/native-go/i18n/messages/ko.json +1 -0
- package/templates/native-go/i18n/messages/zh-CN.json +1 -0
- package/templates/native-go/i18n/messages/zh-TW.json +1 -0
- package/templates/native-go/ui/app.css +10 -0
- package/templates/native-go/ui/app.js +11 -1
- package/templates/native-go-delegate/DELEGATE.md +126 -5
- package/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
- package/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
- package/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
- package/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
- package/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
- package/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
- package/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
- package/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
- package/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
- package/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
- package/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
- package/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
- package/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
- package/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
- package/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
- package/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
- package/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
- package/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
- package/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
- package/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
- package/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
- package/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
- package/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
- package/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
- package/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
- package/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
- package/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
- package/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
- package/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
- package/templates/native-go-delegate/test.sh +1 -0
- package/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
- package/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
- package/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
- package/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
- package/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
- package/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
- package/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
- package/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
- package/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
- package/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
- package/templates/native-go-vue/README.md +4 -0
- package/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-go-vue/frontend/src/App.vue +18 -13
- package/templates/native-go-vue/frontend/src/context.ts +31 -0
- package/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +52 -8
- package/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
- package/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
- package/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +4 -2
- package/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
- package/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/de.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/en.json +12 -2
- package/templates/native-go-vue/frontend/src/delegate/i18n/es.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/it.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +15 -5
- package/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
- package/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
- package/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
- package/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
- package/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n.ts +13 -0
- package/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
- package/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
- package/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
- package/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
- package/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
- package/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
- package/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
- package/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
- package/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
- package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
- package/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
- package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
- package/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
- package/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
- package/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
|
@@ -8,11 +8,13 @@ import (
|
|
|
8
8
|
"os"
|
|
9
9
|
"path/filepath"
|
|
10
10
|
"strings"
|
|
11
|
+
"sync"
|
|
11
12
|
"testing"
|
|
12
13
|
"time"
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
type fakeDSM struct {
|
|
17
|
+
apiMu sync.Mutex
|
|
16
18
|
user Subject
|
|
17
19
|
accountErr, privilegeErr error
|
|
18
20
|
apiCalls int
|
|
@@ -23,10 +25,12 @@ func (f *fakeDSM) Verify(context.Context, string, string) (string, error) {
|
|
|
23
25
|
return f.user.Username, nil
|
|
24
26
|
}
|
|
25
27
|
func (f *fakeDSM) Account(context.Context, string) (Subject, error) { return f.user, f.accountErr }
|
|
26
|
-
func (f *fakeDSM) Allow(context.Context, Subject, string) error
|
|
28
|
+
func (f *fakeDSM) Allow(context.Context, Subject, string, string) error { return f.privilegeErr }
|
|
27
29
|
func (f *fakeDSM) ScopeRoot(context.Context, Subject, string) (string, error) { return f.root, nil }
|
|
28
30
|
func (f *fakeDSM) API(context.Context, string, string, map[string]any) (json.RawMessage, error) {
|
|
31
|
+
f.apiMu.Lock()
|
|
29
32
|
f.apiCalls++
|
|
33
|
+
f.apiMu.Unlock()
|
|
30
34
|
return json.RawMessage(`{"allowed":true}`), nil
|
|
31
35
|
}
|
|
32
36
|
|
|
@@ -69,7 +73,6 @@ func TestRejections(t *testing.T) {
|
|
|
69
73
|
{"missing account", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.accountErr = errors.New("missing") }, nil, "INELIGIBLE"},
|
|
70
74
|
{"disabled", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.user.Expired = "now" }, nil, "INELIGIBLE"},
|
|
71
75
|
{"unknown disabled state", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.user.Expired = "" }, nil, "INELIGIBLE"},
|
|
72
|
-
{"admin runner", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.user.Admin = true }, nil, "INELIGIBLE"},
|
|
73
76
|
{"system runner", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.user.UID = 1 }, nil, "INELIGIBLE"},
|
|
74
77
|
{"uid reuse", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.user.UID++ }, nil, "INELIGIBLE"},
|
|
75
78
|
{"app deny", func(e *Executor, f *fakeDSM, w *fakeWriter, id string) { f.privilegeErr = errors.New("deny") }, nil, "APP_DENIED"},
|
|
@@ -216,7 +219,7 @@ func TestFileStationPrivilegeRequiredSeparately(t *testing.T) {
|
|
|
216
219
|
|
|
217
220
|
type selectivePrivilege struct{ *fakeDSM }
|
|
218
221
|
|
|
219
|
-
func (f *selectivePrivilege) Allow(_ context.Context, _ Subject, app string) error {
|
|
222
|
+
func (f *selectivePrivilege) Allow(_ context.Context, _ Subject, app, _ string) error {
|
|
220
223
|
if app == "SYNO.SDS.App.FileStation3.Instance" {
|
|
221
224
|
return errors.New("deny File Station")
|
|
222
225
|
}
|
|
@@ -230,12 +233,39 @@ func TestSharedScope(t *testing.T) {
|
|
|
230
233
|
t.Fatal(out)
|
|
231
234
|
}
|
|
232
235
|
}
|
|
236
|
+
|
|
237
|
+
type entryRecorder struct {
|
|
238
|
+
*fakeDSM
|
|
239
|
+
entries map[string]string
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
func (f *entryRecorder) Allow(_ context.Context, _ Subject, app, entry string) error {
|
|
243
|
+
f.entries[app] = entry
|
|
244
|
+
return nil
|
|
245
|
+
}
|
|
246
|
+
func TestPackageEntryModeReachesAppPrivilegeOnly(t *testing.T) {
|
|
247
|
+
e, f, _ := setup(t)
|
|
248
|
+
e.Policy.Entry = "app-privilege"
|
|
249
|
+
r := &entryRecorder{fakeDSM: f, entries: map[string]string{}}
|
|
250
|
+
e.DSM = r
|
|
251
|
+
if out := request(e, "delegate.create", map[string]any{"job_id": "j", "ops": []string{"files.list"}, "scope": "home", "path": "/home", "ttl_seconds": 10}); !out.OK {
|
|
252
|
+
t.Fatal(out)
|
|
253
|
+
}
|
|
254
|
+
// File Station is a DSM App without the package's entry mode.
|
|
255
|
+
if r.entries["app"] != "app-privilege" || r.entries["SYNO.SDS.App.FileStation3.Instance"] != "" {
|
|
256
|
+
t.Fatal(r.entries)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
233
259
|
func TestPolicyValidation(t *testing.T) {
|
|
234
260
|
base := Policy{Version: 1, Package: "p2probe", App: "app", Scope: "home", Operations: allOps}
|
|
235
|
-
|
|
236
|
-
|
|
261
|
+
for _, entry := range []string{"", "admin-only", "app-privilege"} {
|
|
262
|
+
p := base
|
|
263
|
+
p.Entry = entry
|
|
264
|
+
if validatePolicy(p, "p2probe") != nil {
|
|
265
|
+
t.Fatal("valid policy", entry)
|
|
266
|
+
}
|
|
237
267
|
}
|
|
238
|
-
for _, mutate := range []func(*Policy){func(p *Policy) { p.Package = "another" }, func(p *Policy) { p.Version = 2 }, func(p *Policy) { p.Operations = []string{"shell"} }, func(p *Policy) { p.Operations = []string{"status", "status"} }, func(p *Policy) { p.Scope = "../../etc" }, func(p *Policy) { p.Root = map[string]string{"a": "bad"} }} {
|
|
268
|
+
for _, mutate := range []func(*Policy){func(p *Policy) { p.Package = "another" }, func(p *Policy) { p.Version = 2 }, func(p *Policy) { p.Operations = []string{"shell"} }, func(p *Policy) { p.Operations = []string{"status", "status"} }, func(p *Policy) { p.Scope = "../../etc" }, func(p *Policy) { p.Root = map[string]string{"a": "bad"} }, func(p *Policy) { p.Entry = "everyone" }} {
|
|
239
269
|
p := base
|
|
240
270
|
mutate(&p)
|
|
241
271
|
if validatePolicy(p, "p2probe") == nil {
|
|
@@ -16,7 +16,7 @@ type identitySwitch interface {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
func dropIdentity(x identitySwitch, s Subject) error {
|
|
19
|
-
if s.UID < 1024 || s.GID < 0 || len(s.Groups) == 0
|
|
19
|
+
if s.UID < 1024 || s.GID < 0 || len(s.Groups) == 0 {
|
|
20
20
|
return errors.New("subject")
|
|
21
21
|
}
|
|
22
22
|
for _, g := range s.Groups {
|
|
@@ -46,3 +46,29 @@ func dropIdentity(x identitySwitch, s Subject) error {
|
|
|
46
46
|
}
|
|
47
47
|
return nil
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
func sameGroups(a, b []int) bool {
|
|
51
|
+
a = append([]int(nil), a...)
|
|
52
|
+
b = append([]int(nil), b...)
|
|
53
|
+
sort.Ints(a)
|
|
54
|
+
sort.Ints(b)
|
|
55
|
+
return fmt.Sprint(a) == fmt.Sprint(b)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Keep the historical injectable identity interface for existing consumer
|
|
59
|
+
// fixtures. Production fixed children require this stricter syscall surface.
|
|
60
|
+
type sealedIdentitySwitch interface {
|
|
61
|
+
identitySwitch
|
|
62
|
+
Seal() error
|
|
63
|
+
VerifyPrivileges(Subject) error
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func dropSealedIdentity(x sealedIdentitySwitch, s Subject) error {
|
|
67
|
+
if err := x.Seal(); err != nil {
|
|
68
|
+
return err
|
|
69
|
+
}
|
|
70
|
+
if err := dropIdentity(x, s); err != nil {
|
|
71
|
+
return err
|
|
72
|
+
}
|
|
73
|
+
return x.VerifyPrivileges(s)
|
|
74
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//go:build linux
|
|
2
|
+
|
|
3
|
+
package main
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"fmt"
|
|
7
|
+
"os"
|
|
8
|
+
"os/exec"
|
|
9
|
+
"runtime"
|
|
10
|
+
"syscall"
|
|
11
|
+
"testing"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
func TestSealedIdentityRealKernel(t *testing.T) {
|
|
15
|
+
if mode := os.Getenv("T0188_IDENTITY_CHILD"); mode != "" {
|
|
16
|
+
runtime.LockOSThread()
|
|
17
|
+
subject := Subject{UID: 1200, GID: 100, Groups: []int{100}}
|
|
18
|
+
var err error
|
|
19
|
+
if mode == "unsealed" {
|
|
20
|
+
// Clear capabilities and IDs without setting no_new_privs.
|
|
21
|
+
// VerifyPrivileges must still refuse this otherwise sealed child.
|
|
22
|
+
for cap := uintptr(0); cap < 64; cap++ {
|
|
23
|
+
_, _, errno := syscall.Syscall6(syscall.SYS_PRCTL, 24, cap, 0, 0, 0, 0)
|
|
24
|
+
if errno != 0 && errno != syscall.EINVAL {
|
|
25
|
+
fmt.Fprintln(os.Stderr, errno)
|
|
26
|
+
os.Exit(1)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
err = dropIdentity(realIdentity{}, subject)
|
|
30
|
+
if err == nil {
|
|
31
|
+
err = realIdentity{}.VerifyPrivileges(subject)
|
|
32
|
+
}
|
|
33
|
+
if err == nil || err.Error() != "no_new_privs missing" {
|
|
34
|
+
fmt.Fprintln(os.Stderr, "expected no_new_privs refusal, got", err)
|
|
35
|
+
os.Exit(1)
|
|
36
|
+
}
|
|
37
|
+
os.Exit(0)
|
|
38
|
+
}
|
|
39
|
+
err = dropSealedIdentity(realIdentity{}, subject)
|
|
40
|
+
if err != nil {
|
|
41
|
+
fmt.Fprintln(os.Stderr, err)
|
|
42
|
+
os.Exit(1)
|
|
43
|
+
}
|
|
44
|
+
os.Exit(0)
|
|
45
|
+
}
|
|
46
|
+
if os.Geteuid() != 0 {
|
|
47
|
+
t.Skip("root Linux fixture required")
|
|
48
|
+
}
|
|
49
|
+
exe, err := os.Executable()
|
|
50
|
+
if err != nil {
|
|
51
|
+
t.Fatal(err)
|
|
52
|
+
}
|
|
53
|
+
for _, mode := range []string{"sealed", "unsealed"} {
|
|
54
|
+
cmd := exec.Command(exe, "-test.run=^TestSealedIdentityRealKernel$")
|
|
55
|
+
cmd.Env = append(os.Environ(), "T0188_IDENTITY_CHILD="+mode)
|
|
56
|
+
if out, err := cmd.CombinedOutput(); err != nil {
|
|
57
|
+
t.Fatalf("%s subject kernel verification: %s: %v", mode, out, err)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//go:build linux
|
|
2
|
+
|
|
3
|
+
package main
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"errors"
|
|
7
|
+
"fmt"
|
|
8
|
+
"os"
|
|
9
|
+
"strconv"
|
|
10
|
+
"strings"
|
|
11
|
+
"syscall"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
func (realIdentity) Seal() error {
|
|
15
|
+
// These are per-thread Linux settings. Every fresh child locks its OS thread
|
|
16
|
+
// until exit; it never execs untrusted code after dropping the identity.
|
|
17
|
+
prctl := func(op, a uintptr) error {
|
|
18
|
+
_, _, err := syscall.Syscall6(syscall.SYS_PRCTL, op, a, 0, 0, 0, 0)
|
|
19
|
+
if err != 0 {
|
|
20
|
+
return err
|
|
21
|
+
}
|
|
22
|
+
return nil
|
|
23
|
+
}
|
|
24
|
+
if err := prctl(38, 1); err != nil {
|
|
25
|
+
return err
|
|
26
|
+
} // PR_SET_NO_NEW_PRIVS
|
|
27
|
+
if err := prctl(8, 0); err != nil {
|
|
28
|
+
return err
|
|
29
|
+
} // PR_SET_KEEPCAPS off
|
|
30
|
+
for cap := uintptr(0); cap < 64; cap++ {
|
|
31
|
+
if err := prctl(24, cap); err != nil && err != syscall.EINVAL {
|
|
32
|
+
return err
|
|
33
|
+
}
|
|
34
|
+
} // PR_CAPBSET_DROP
|
|
35
|
+
return nil
|
|
36
|
+
}
|
|
37
|
+
func (realIdentity) VerifyPrivileges(s Subject) error {
|
|
38
|
+
b, err := os.ReadFile(fmt.Sprintf("/proc/self/task/%d/status", syscall.Gettid()))
|
|
39
|
+
if err != nil {
|
|
40
|
+
return err
|
|
41
|
+
}
|
|
42
|
+
fields := map[string][]string{}
|
|
43
|
+
for _, line := range strings.Split(string(b), "\n") {
|
|
44
|
+
parts := strings.Fields(line)
|
|
45
|
+
if len(parts) > 1 {
|
|
46
|
+
fields[strings.TrimSuffix(parts[0], ":")] = parts[1:]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for key, want := range map[string]int{"Uid": s.UID, "Gid": s.GID} {
|
|
50
|
+
got := fields[key]
|
|
51
|
+
if len(got) != 4 {
|
|
52
|
+
return errors.New("saved IDs missing")
|
|
53
|
+
}
|
|
54
|
+
for _, v := range got {
|
|
55
|
+
n, err := strconv.Atoi(v)
|
|
56
|
+
if err != nil || n != want {
|
|
57
|
+
return errors.New("saved IDs mismatch")
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for _, key := range []string{"CapInh", "CapPrm", "CapEff", "CapBnd", "CapAmb"} {
|
|
62
|
+
v := fields[key]
|
|
63
|
+
if len(v) != 1 {
|
|
64
|
+
return errors.New("capability missing")
|
|
65
|
+
}
|
|
66
|
+
n, err := strconv.ParseUint(v[0], 16, 64)
|
|
67
|
+
if err != nil || n != 0 {
|
|
68
|
+
return errors.New("capability retained")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Linux 4.4 supports no_new_privs but does not expose NoNewPrivs in
|
|
72
|
+
// proc status. Query the locked writer thread directly; missing/failed
|
|
73
|
+
// kernel support still refuses the write, without relaxing the seal.
|
|
74
|
+
nnp, _, errno := syscall.Syscall6(syscall.SYS_PRCTL, 39, 0, 0, 0, 0, 0) // PR_GET_NO_NEW_PRIVS
|
|
75
|
+
if errno != 0 {
|
|
76
|
+
return errno
|
|
77
|
+
}
|
|
78
|
+
if nnp != 1 {
|
|
79
|
+
return errors.New("no_new_privs missing")
|
|
80
|
+
}
|
|
81
|
+
return nil
|
|
82
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"errors"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
type secureSwitch struct {
|
|
9
|
+
sealed, verified bool
|
|
10
|
+
bad bool
|
|
11
|
+
subject Subject
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func (s *secureSwitch) Seal() error { s.sealed = true; return nil }
|
|
15
|
+
func (s *secureSwitch) VerifyPrivileges(Subject) error {
|
|
16
|
+
s.verified = true
|
|
17
|
+
if s.bad {
|
|
18
|
+
return errors.New("saved root or capability")
|
|
19
|
+
}
|
|
20
|
+
return nil
|
|
21
|
+
}
|
|
22
|
+
func (s *secureSwitch) Setgroups([]int) error {
|
|
23
|
+
if !s.sealed {
|
|
24
|
+
return errors.New("not sealed")
|
|
25
|
+
}
|
|
26
|
+
return nil
|
|
27
|
+
}
|
|
28
|
+
func (s *secureSwitch) Setresgid(int, int, int) error { return nil }
|
|
29
|
+
func (s *secureSwitch) Setresuid(int, int, int) error { return nil }
|
|
30
|
+
func (s *secureSwitch) IDs() (int, int, int, int) {
|
|
31
|
+
return s.subject.UID, s.subject.UID, s.subject.GID, s.subject.GID
|
|
32
|
+
}
|
|
33
|
+
func (s *secureSwitch) Groups() ([]int, error) { return s.subject.Groups, nil }
|
|
34
|
+
func TestDropAdminSealsAndChecksSavedIDsCapabilities(t *testing.T) {
|
|
35
|
+
subject := Subject{UID: 1200, GID: 100, Groups: []int{100, 101}, Admin: true}
|
|
36
|
+
for _, bad := range []bool{false, true} {
|
|
37
|
+
s := &secureSwitch{bad: bad, subject: subject}
|
|
38
|
+
err := dropSealedIdentity(s, subject)
|
|
39
|
+
if (err != nil) != bad || !s.verified {
|
|
40
|
+
t.Fatal("unverified privilege drop", err)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -69,6 +69,11 @@ func Run(ctx context.Context, cfg Config, action string) error {
|
|
|
69
69
|
defer ticker.Stop()
|
|
70
70
|
for {
|
|
71
71
|
gone, err := absent(cfg.Socket)
|
|
72
|
+
if err == nil && gone && action == "purge" {
|
|
73
|
+
// A paused executor has no socket but still polls the mailbox. Only
|
|
74
|
+
// its purge removes the socket directory, after root cleanup.
|
|
75
|
+
gone, err = absent(filepath.Dir(cfg.Socket))
|
|
76
|
+
}
|
|
72
77
|
if err != nil {
|
|
73
78
|
if cfg.Log != nil {
|
|
74
79
|
cfg.Log("executor socket status unavailable: request retained; lifecycle continues")
|
|
@@ -13,7 +13,8 @@ func TestRequestPersistsOfflineWithoutScheduler(t *testing.T) {
|
|
|
13
13
|
for _, action := range []string{"stop", "purge"} {
|
|
14
14
|
t.Run(action, func(t *testing.T) {
|
|
15
15
|
root := t.TempDir()
|
|
16
|
-
|
|
16
|
+
// No executor ever ran: its socket directory does not exist.
|
|
17
|
+
cfg := Config{Package: "TestApp", Data: root, Socket: filepath.Join(root, "run", "executor.sock")}
|
|
17
18
|
if err := Run(context.Background(), cfg, action); err != nil {
|
|
18
19
|
t.Fatal(err)
|
|
19
20
|
}
|
|
@@ -34,7 +35,8 @@ func TestRequestWaitsForSocketAndTimeoutDoesNotBlockUninstall(t *testing.T) {
|
|
|
34
35
|
for _, timeout := range []bool{false, true} {
|
|
35
36
|
t.Run(action+"-"+map[bool]string{false: "confirmed", true: "timeout"}[timeout], func(t *testing.T) {
|
|
36
37
|
root := t.TempDir()
|
|
37
|
-
|
|
38
|
+
os.Mkdir(filepath.Join(root, "run"), 0750)
|
|
39
|
+
socket := filepath.Join(root, "run", "executor.sock")
|
|
38
40
|
os.WriteFile(socket, []byte{}, 0600)
|
|
39
41
|
warnings := []string{}
|
|
40
42
|
cfg := Config{Package: "TestApp", Data: root, Socket: socket, Log: func(s string) { warnings = append(warnings, s) }}
|
|
@@ -50,7 +52,12 @@ func TestRequestWaitsForSocketAndTimeoutDoesNotBlockUninstall(t *testing.T) {
|
|
|
50
52
|
defer close(done)
|
|
51
53
|
for {
|
|
52
54
|
if _, err := os.Stat(filepath.Join(root, "executor", "control")); err == nil {
|
|
53
|
-
|
|
55
|
+
// Pause closes the socket; purge ends with its directory.
|
|
56
|
+
if action == "purge" {
|
|
57
|
+
os.RemoveAll(filepath.Dir(socket))
|
|
58
|
+
} else {
|
|
59
|
+
os.Remove(socket)
|
|
60
|
+
}
|
|
54
61
|
return
|
|
55
62
|
}
|
|
56
63
|
select {
|
|
@@ -80,6 +87,57 @@ func TestRequestWaitsForSocketAndTimeoutDoesNotBlockUninstall(t *testing.T) {
|
|
|
80
87
|
}
|
|
81
88
|
}
|
|
82
89
|
}
|
|
90
|
+
|
|
91
|
+
// A stopped package already paused the executor and removed its socket, so
|
|
92
|
+
// preuninst's purge must wait for the root purge itself: the executor removes
|
|
93
|
+
// its socket directory only after consuming purge. Returning earlier lets DSM
|
|
94
|
+
// delete the mailbox before the paused monitor polls it.
|
|
95
|
+
func TestPurgeOfPausedExecutorWaitsForSocketDirectoryRemoval(t *testing.T) {
|
|
96
|
+
root := t.TempDir()
|
|
97
|
+
dir := filepath.Join(root, "run")
|
|
98
|
+
os.Mkdir(dir, 0750)
|
|
99
|
+
cfg := Config{Package: "TestApp", Data: root, Socket: filepath.Join(dir, "executor.sock")}
|
|
100
|
+
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
101
|
+
defer cancel()
|
|
102
|
+
consumed := make(chan time.Time, 1)
|
|
103
|
+
go func() {
|
|
104
|
+
for ctx.Err() == nil {
|
|
105
|
+
if b, _ := os.ReadFile(filepath.Join(root, "executor", "control")); string(b) == "purge\n" {
|
|
106
|
+
time.Sleep(300 * time.Millisecond)
|
|
107
|
+
consumed <- time.Now()
|
|
108
|
+
os.RemoveAll(dir)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
time.Sleep(time.Millisecond)
|
|
112
|
+
}
|
|
113
|
+
}()
|
|
114
|
+
if err := Run(ctx, cfg, "purge"); err != nil {
|
|
115
|
+
t.Fatal(err)
|
|
116
|
+
}
|
|
117
|
+
select {
|
|
118
|
+
case <-consumed:
|
|
119
|
+
default:
|
|
120
|
+
t.Fatal("purge returned before the executor removed its socket directory")
|
|
121
|
+
}
|
|
122
|
+
if ctx.Err() != nil {
|
|
123
|
+
t.Fatal("purge confirmation timed out")
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
func TestStopOfPausedExecutorDoesNotWaitForSocketDirectory(t *testing.T) {
|
|
128
|
+
root := t.TempDir()
|
|
129
|
+
dir := filepath.Join(root, "run")
|
|
130
|
+
os.Mkdir(dir, 0750)
|
|
131
|
+
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
132
|
+
defer cancel()
|
|
133
|
+
if err := Run(ctx, Config{Package: "TestApp", Data: root, Socket: filepath.Join(dir, "executor.sock")}, "stop"); err != nil {
|
|
134
|
+
t.Fatal(err)
|
|
135
|
+
}
|
|
136
|
+
if ctx.Err() != nil {
|
|
137
|
+
t.Fatal("stop waited for the socket directory")
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
83
141
|
func TestRequestRejectsInvalidActionAndSymlink(t *testing.T) {
|
|
84
142
|
root := t.TempDir()
|
|
85
143
|
cfg := Config{Package: "TestApp", Data: root, Socket: filepath.Join(root, "socket")}
|
|
@@ -8,24 +8,24 @@ q=/var/packages/$p
|
|
|
8
8
|
s=$q/target/executor
|
|
9
9
|
r=/usr/local/etc/synopkgland/$p
|
|
10
10
|
d=$r/runtime
|
|
11
|
-
|
|
12
|
-
@POLICY_DIGEST@ $
|
|
11
|
+
o="--package $p"
|
|
12
|
+
v(){ echo "$2@POLICY_DIGEST@ ${1}policy.json"|sha256sum -c - >/dev/null||{ logger digest;exit 1;};}
|
|
13
13
|
a=purge
|
|
14
14
|
if [ -d $q ];then
|
|
15
15
|
a=stop
|
|
16
|
-
[ "$(cat
|
|
16
|
+
[ "$(cat $q/var/executor/control)" != purge ] || { a=purge;[ -e $d ] || [ -L $d ] || { logger purged;exit 0;};}
|
|
17
17
|
else [ -d $r ] || exit 0;fi
|
|
18
|
-
[ $a = stop ] || s=$d
|
|
19
|
-
v $s/
|
|
20
18
|
mkdir -p -m 700 $d
|
|
21
19
|
[ "$(find $d -maxdepth 0 -uid 0 -type d -perm 700)" = $d ]
|
|
22
20
|
cd $d
|
|
21
|
+
[ $a = stop ] || { v ./ "";exec ./executor control purge $o;}
|
|
22
|
+
e=$(sed -n 's/^synopkgland_executor_sha256="\([0-9a-f]*\)"$/\1/p' $q/INFO)
|
|
23
|
+
[ ${#e} = 64 ]
|
|
23
24
|
cp $s/executor .executor
|
|
24
25
|
cp $s/policy.json .policy.json
|
|
25
|
-
v .
|
|
26
|
+
v . "$e .executor
|
|
27
|
+
"
|
|
26
28
|
chmod 700 .executor
|
|
27
|
-
./.executor control $a --package $p
|
|
28
|
-
[ $a = stop ] || exit 0
|
|
29
29
|
for f in executor policy.json;do mv .$f $f;done
|
|
30
30
|
[ -e $s/../root ] && cp -R $s/../root .
|
|
31
|
-
./executor control start
|
|
31
|
+
./executor control start $o
|
|
@@ -8,10 +8,10 @@ import (
|
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
func main() {
|
|
11
|
-
if len(os.Args) !=
|
|
11
|
+
if len(os.Args) != 3 {
|
|
12
12
|
os.Exit(2)
|
|
13
13
|
}
|
|
14
|
-
tasks, err := taskscript.Generate(os.Args[1], os.Args[2]
|
|
14
|
+
tasks, err := taskscript.Generate(os.Args[1], os.Args[2])
|
|
15
15
|
if err != nil {
|
|
16
16
|
os.Exit(1)
|
|
17
17
|
}
|
|
@@ -8,19 +8,24 @@ q=/var/packages/$p
|
|
|
8
8
|
s=$q/target/executor
|
|
9
9
|
r=/usr/local/etc/synopkgland/$p
|
|
10
10
|
d=$r/runtime
|
|
11
|
-
v(){
|
|
12
|
-
v "$s" ''
|
|
11
|
+
v(){ echo "$3@POLICY_DIGEST@ $1/$2policy.json"|sha256sum -c - >/dev/null || { logger digest;exit 1;};}
|
|
13
12
|
mkdir -p -m 700 "$d"
|
|
14
13
|
[ "$(find "$d" -maxdepth 0 -uid 0 -type d -perm 700)" = "$d" ]
|
|
15
|
-
a=$(cat /var/
|
|
14
|
+
a=$(cat "$q/var/executor/control")
|
|
16
15
|
case "$a" in start|stop|purge) ;; *) exit 1;; esac
|
|
17
|
-
if [ "$a" =
|
|
16
|
+
if [ "$a" = stop ]; then
|
|
17
|
+
v "$d" '' ''
|
|
18
|
+
exec "$d/executor" control stop --package "$p"
|
|
19
|
+
fi
|
|
20
|
+
# Root runs only executor bytes anchored in the root-owned INFO, under the approved policy.
|
|
21
|
+
e=$(sed -n 's/^synopkgland_executor_sha256="\([0-9a-f]*\)"$/\1/p' "$q/INFO")
|
|
22
|
+
[ ${#e} = 64 ] || { logger anchor;exit 1;}
|
|
18
23
|
cp "$s/executor" "$d/.executor"
|
|
19
24
|
cp "$s/policy.json" "$d/.policy.json"
|
|
20
|
-
v "$d" .
|
|
25
|
+
v "$d" . "$e $d/.executor
|
|
26
|
+
"
|
|
21
27
|
chmod 700 "$d/.executor"
|
|
22
|
-
"$d/.executor" control purge --package "$p"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"$d/executor" control
|
|
26
|
-
fi
|
|
28
|
+
[ "$a" = start ] || exec "$d/.executor" control purge --package "$p"
|
|
29
|
+
for f in executor policy.json; do mv "$d/.$f" "$d/$f"; done
|
|
30
|
+
[ -e "$s/../root" ] && cp -R "$s/../root" "$d"
|
|
31
|
+
"$d/executor" control start --package "$p"
|
|
@@ -21,11 +21,13 @@ type Task struct {
|
|
|
21
21
|
Script string `json:"script"`
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// Tasks pin only the approved policy. Executor bytes are anchored per SPK in the
|
|
25
|
+
// root-owned package INFO, so an executor-only upgrade keeps both definitions.
|
|
26
|
+
func Generate(pkg, pd string) ([]Task, error) {
|
|
27
|
+
if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]{1,63}$`).MatchString(pkg) || !regexp.MustCompile(`^[a-f0-9]{64}$`).MatchString(pd) {
|
|
26
28
|
return nil, errors.New("task pins")
|
|
27
29
|
}
|
|
28
|
-
replace := strings.NewReplacer("@PACKAGE@", pkg, "@
|
|
30
|
+
replace := strings.NewReplacer("@PACKAGE@", pkg, "@POLICY_DIGEST@", pd)
|
|
29
31
|
tasks := []Task{}
|
|
30
32
|
for i, source := range []string{boot, control} {
|
|
31
33
|
kind, limit := "boot", 1024
|
|
@@ -84,3 +84,14 @@ func TestDirectoryValidationRejectsExistingWrongModeOwnerAndSymlink(t *testing.T
|
|
|
84
84
|
t.Fatal("symlink accepted")
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
+
|
|
88
|
+
// The legacy write child linked its own copy without waiting for serve, so an
|
|
89
|
+
// orphan could still publish. Nothing spawns it since files.write moved to the
|
|
90
|
+
// move child; neither it nor its cleanup child may run at all.
|
|
91
|
+
func TestLegacyWriteChildrenAreNotCommands(t *testing.T) {
|
|
92
|
+
for _, child := range []string{"write-child", "cleanup-child"} {
|
|
93
|
+
if err := run([]string{child}); err == nil || err.Error() != "invalid command" {
|
|
94
|
+
t.Fatalf("%s: %v", child, err)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//go:build linux
|
|
2
|
+
|
|
3
|
+
package main
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"fmt"
|
|
7
|
+
"os"
|
|
8
|
+
"syscall"
|
|
9
|
+
"unsafe"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func linkOpenPart(part, dir *os.File, name string) error {
|
|
13
|
+
// /proc/self/fd/<fd> refers to the still-open inode. Following that one trusted
|
|
14
|
+
// proc link prevents a subject from swapping a guessed temporary pathname.
|
|
15
|
+
old, err := syscall.BytePtrFromString(fmt.Sprintf("/proc/self/fd/%d", part.Fd()))
|
|
16
|
+
if err != nil {
|
|
17
|
+
return err
|
|
18
|
+
}
|
|
19
|
+
new, err := syscall.BytePtrFromString(name)
|
|
20
|
+
if err != nil {
|
|
21
|
+
return err
|
|
22
|
+
}
|
|
23
|
+
_, _, errno := syscall.Syscall6(syscall.SYS_LINKAT, ^uintptr(99), uintptr(unsafe.Pointer(old)), dir.Fd(), uintptr(unsafe.Pointer(new)), 0x400, 0)
|
|
24
|
+
if errno != 0 {
|
|
25
|
+
return errno
|
|
26
|
+
}
|
|
27
|
+
return nil
|
|
28
|
+
}
|