@synopackageland/cli 0.3.10 → 0.4.1
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/LICENSE +21 -0
- package/README.md +57 -9
- package/dist/bin.js +1 -2
- package/dist/build-spk/generator.d.ts +0 -3
- package/dist/build-spk/generator.js +138 -287
- package/dist/build-spk/native-lifecycle.js +0 -3
- package/dist/build-spk/native-payload.js +0 -1
- package/dist/build-spk/notices.d.ts +5 -0
- package/dist/build-spk/notices.js +60 -0
- package/dist/cli.js +178 -151
- package/dist/compose/analyze.d.ts +1 -2
- package/dist/compose/analyze.js +5 -48
- package/dist/contract/unsupported-types.d.ts +10 -0
- package/dist/contract/unsupported-types.js +49 -0
- package/dist/contract/validate.js +25 -2
- package/dist/contract/web-launch.js +0 -2
- package/dist/deploy/deploy.d.ts +1 -4
- package/dist/deploy/deploy.js +45 -156
- package/dist/deploy/homes-values.js +1 -1
- package/dist/deploy/plan.d.ts +18 -0
- package/dist/deploy/plan.js +54 -0
- package/dist/deploy/spk-version.d.ts +2 -14
- package/dist/deploy/spk-version.js +25 -111
- package/dist/dev.d.ts +1 -3
- package/dist/dev.js +14 -28
- package/dist/error-registry.js +830 -862
- package/dist/host/dsm-client.js +12 -272
- package/dist/host/dsm-port-profile.d.ts +0 -1
- package/dist/host/dsm-port-profile.js +0 -2
- package/dist/host/types.d.ts +1 -83
- package/dist/index.d.ts +0 -9
- package/dist/index.js +0 -6
- package/dist/info.d.ts +0 -1
- package/dist/info.js +3 -10
- package/dist/init.d.ts +15 -1
- package/dist/init.js +128 -12
- package/dist/log.js +2 -3
- package/dist/native/validate.js +0 -1
- package/dist/standalone/binary.d.ts +9 -0
- package/dist/standalone/binary.js +67 -0
- package/dist/standalone/build.d.ts +25 -0
- package/dist/standalone/build.js +110 -0
- package/dist/standalone/daemon.d.ts +23 -0
- package/dist/standalone/daemon.js +114 -0
- package/dist/standalone/dsm-window.d.ts +26 -0
- package/dist/standalone/dsm-window.js +291 -0
- package/dist/standalone/helper-inventory.d.ts +16 -0
- package/dist/standalone/helper-inventory.js +2 -0
- package/dist/standalone/helper.d.ts +21 -0
- package/dist/standalone/helper.js +105 -0
- package/dist/standalone/host-adapter.d.ts +5 -0
- package/dist/standalone/host-adapter.js +148 -0
- package/dist/standalone/host-platform.d.ts +13 -0
- package/dist/standalone/host-platform.js +42 -0
- package/dist/standalone/host-types.d.ts +49 -0
- package/dist/standalone/host-types.js +1 -0
- package/dist/standalone/i18n.d.ts +28 -0
- package/dist/standalone/i18n.js +161 -0
- package/dist/standalone/inspect-helper.d.ts +6 -0
- package/dist/standalone/inspect-helper.js +88 -0
- package/dist/standalone/inspect-spk.d.ts +23 -0
- package/dist/standalone/inspect-spk.js +209 -0
- package/dist/standalone/lifecycle-helper.d.ts +2 -0
- package/dist/standalone/lifecycle-helper.js +12 -0
- package/dist/standalone/lifecycle.d.ts +3 -0
- package/dist/standalone/lifecycle.js +53 -0
- package/dist/standalone/manifest.d.ts +73 -0
- package/dist/standalone/manifest.js +279 -0
- package/dist/standalone/reopen-events.d.ts +2 -0
- package/dist/standalone/reopen-events.js +28 -0
- package/dist/standalone/root-messages.d.ts +7 -0
- package/dist/standalone/root-messages.js +259 -0
- package/dist/standalone/root-ops.d.ts +42 -0
- package/dist/standalone/root-ops.js +101 -0
- package/dist/standalone/root-window.d.ts +36 -0
- package/dist/standalone/root-window.js +302 -0
- package/dist/standalone/spk.d.ts +23 -0
- package/dist/standalone/spk.js +192 -0
- package/dist/template-paths.d.ts +2 -0
- package/dist/template-paths.js +9 -0
- package/dist/templates/_daemon/fixture_linux_test.go +15 -0
- package/dist/templates/_daemon/fixture_other_test.go +7 -0
- package/dist/templates/_daemon/go.mod +3 -0
- package/dist/templates/_daemon/main.go +608 -0
- package/dist/templates/_daemon/main_test.go +242 -0
- package/dist/templates/_daemon/process_linux.go +55 -0
- package/dist/templates/_daemon/process_linux_test.go +161 -0
- package/dist/templates/_daemon/process_other.go +14 -0
- package/dist/templates/_daemon/testdata/child.go +41 -0
- package/dist/templates/_shared/GO-LICENSE +27 -0
- package/dist/templates/_shared/GO-PATENTS +22 -0
- package/dist/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/dist/templates/_shared/notice-overrides/index.json +14 -0
- package/dist/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/dist/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/dist/templates/_shared/third-party-notices.mjs +51 -0
- package/dist/templates/binary/synology-app.yaml +7 -0
- package/dist/templates/hello-files/compose.yaml +0 -1
- package/dist/templates/hello-web/compose.yaml +13 -10
- package/dist/templates/hello-web/html/app.js +1 -23
- package/dist/templates/hello-web/html/index.html +1 -3
- package/dist/templates/hello-web-page/compose.yaml +13 -10
- package/dist/templates/hello-web-page/html/app.js +1 -23
- package/dist/templates/hello-web-page/html/index.html +1 -3
- package/dist/templates/native-go/README.md +324 -0
- package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/dist/templates/native-go/backend/cmd/app/main.go +49 -0
- package/dist/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/dist/templates/native-go/backend/cmd/helper/main.go +38 -0
- package/dist/templates/native-go/backend/go.mod +7 -0
- package/dist/templates/native-go/backend/go.sum +4 -0
- package/dist/templates/native-go/backend/internal/api/binary.go +154 -0
- package/dist/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/dist/templates/native-go/backend/internal/api/errors.go +33 -0
- package/dist/templates/native-go/backend/internal/api/registry.go +104 -0
- package/dist/templates/native-go/backend/internal/api/registry_test.go +329 -0
- package/dist/templates/native-go/backend/internal/api/server.go +159 -0
- package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/dist/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/dist/templates/native-go/backend/internal/app/root_none.go +9 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +138 -0
- package/dist/templates/native-go/backend/internal/app/routes_test.go +172 -0
- package/dist/templates/native-go/backend/internal/dsm/auth.go +118 -0
- package/dist/templates/native-go/backend/internal/dsm/auth_test.go +139 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/dist/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/control.go +424 -0
- package/dist/templates/native-go/backend/internal/helper/control_test.go +250 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/dist/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/dist/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/dist/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/dist/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/dist/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/dist/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/dist/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/dist/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/dist/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/dist/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/dist/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/dist/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/dist/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/dist/templates/native-go/backend/internal/helper/peer_linux.go +44 -0
- package/dist/templates/native-go/backend/internal/helper/peer_other.go +7 -0
- package/dist/templates/native-go/backend/internal/helper/process_linux.go +177 -0
- package/dist/templates/native-go/backend/internal/helper/process_other.go +5 -0
- package/dist/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/dist/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/dist/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/dist/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/server_linux.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/status.go +334 -0
- package/dist/templates/native-go/backend/internal/helper/status_test.go +288 -0
- package/dist/templates/native-go/backend/internal/helper/supervision.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/supervision_test.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +363 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux_test.go +913 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/dist/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/dist/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/dist/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/dist/templates/native-go/backend/internal/helper/write.go +77 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/dist/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/dist/templates/native-go/dsm-package.yaml +58 -0
- package/dist/templates/native-go/gitignore +1 -0
- package/dist/templates/native-go/i18n/glossary.json +662 -0
- package/dist/templates/native-go/i18n/messages/de.json +28 -0
- package/dist/templates/native-go/i18n/messages/en.json +28 -0
- package/dist/templates/native-go/i18n/messages/es.json +28 -0
- package/dist/templates/native-go/i18n/messages/fr.json +28 -0
- package/dist/templates/native-go/i18n/messages/it.json +28 -0
- package/dist/templates/native-go/i18n/messages/ja.json +28 -0
- package/dist/templates/native-go/i18n/messages/ko.json +28 -0
- package/dist/templates/native-go/i18n/messages/zh-CN.json +28 -0
- package/dist/templates/native-go/i18n/messages/zh-TW.json +28 -0
- package/dist/templates/native-go/ui/app.css +35 -0
- package/dist/templates/native-go/ui/app.js +101 -0
- package/dist/templates/native-go-better-auth/backend/internal/app/identity.go +208 -0
- package/dist/templates/native-go-better-auth/backend/internal/app/identity_test.go +113 -0
- package/dist/templates/native-go-better-auth/node/app.mjs +72 -0
- package/dist/templates/native-go-better-auth/node/build.mjs +4 -0
- package/dist/templates/native-go-better-auth/node/package-lock.json +862 -0
- package/dist/templates/native-go-better-auth/node/package.json +1 -0
- package/dist/templates/native-go-better-auth/node/test/auth.test.mjs +31 -0
- package/dist/templates/native-go-integration/backend/internal/app/identity_none.go +6 -0
- package/dist/templates/native-go-integration/backend/internal/app/personal.go +203 -0
- package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +119 -0
- package/dist/templates/native-go-root/backend/internal/app/root.go +107 -0
- package/dist/templates/native-go-root/backend/internal/app/root_test.go +124 -0
- package/dist/templates/native-go-root/root/whoami.sh +6 -0
- package/dist/templates/native-go-vue/README.md +224 -0
- package/dist/templates/native-go-vue/frontend/DESIGN.md +78 -0
- package/dist/templates/native-go-vue/frontend/package-lock.json +2410 -0
- package/dist/templates/native-go-vue/frontend/package.json +6 -0
- package/dist/templates/native-go-vue/frontend/src/App.vue +159 -0
- package/dist/templates/native-go-vue/frontend/src/context.ts +56 -0
- package/dist/templates/native-go-vue/frontend/src/main.ts +29 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/dist/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/dist/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/dist/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/dist/templates/native-go-vue/frontend/src/style.css +31 -0
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +190 -0
- package/dist/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/dist/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/dist/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/dist/templates/native-go-vue/frontend/tsconfig.json +1 -0
- package/dist/templates/native-go-vue/frontend/vite.config.ts +10 -0
- package/dist/templates/native-go-vue/gitignore +2 -0
- package/dist/types.d.ts +1 -1
- package/dist/validate.js +11 -7
- package/package.json +5 -8
- package/schema/synology-app.schema.json +36 -37
- package/skills/SKILL.md +4 -48
- package/skills/reference/create.md +11 -83
- package/skills/reference/deploy.md +7 -78
- package/skills/reference/diagnose.md +4 -101
- package/skills/reference/files.md +5 -41
- package/skills/reference/identity.md +3 -29
- package/skills/reference/wrap.md +0 -2
- package/templates/_daemon/fixture_linux_test.go +15 -0
- package/templates/_daemon/fixture_other_test.go +7 -0
- package/templates/_daemon/go.mod +3 -0
- package/templates/_daemon/main.go +608 -0
- package/templates/_daemon/main_test.go +242 -0
- package/templates/_daemon/process_linux.go +55 -0
- package/templates/_daemon/process_linux_test.go +161 -0
- package/templates/_daemon/process_other.go +14 -0
- package/templates/_daemon/testdata/child.go +41 -0
- package/templates/_shared/GO-LICENSE +27 -0
- package/templates/_shared/GO-PATENTS +22 -0
- package/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/templates/_shared/notice-overrides/index.json +14 -0
- package/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/templates/_shared/third-party-notices.mjs +51 -0
- package/templates/binary/synology-app.yaml +7 -0
- package/templates/hello-files/compose.yaml +0 -1
- package/templates/hello-web/compose.yaml +13 -10
- package/templates/hello-web/html/app.js +1 -23
- package/templates/hello-web/html/index.html +1 -3
- package/templates/hello-web-page/compose.yaml +13 -10
- package/templates/hello-web-page/html/app.js +1 -23
- package/templates/hello-web-page/html/index.html +1 -3
- package/templates/native-go/README.md +324 -0
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/templates/native-go/backend/cmd/app/main.go +49 -0
- package/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/templates/native-go/backend/cmd/helper/main.go +38 -0
- package/templates/native-go/backend/go.mod +7 -0
- package/templates/native-go/backend/go.sum +4 -0
- package/templates/native-go/backend/internal/api/binary.go +154 -0
- package/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/templates/native-go/backend/internal/api/errors.go +33 -0
- package/templates/native-go/backend/internal/api/registry.go +104 -0
- package/templates/native-go/backend/internal/api/registry_test.go +329 -0
- package/templates/native-go/backend/internal/api/server.go +159 -0
- package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/templates/native-go/backend/internal/app/root_none.go +9 -0
- package/templates/native-go/backend/internal/app/routes.go +138 -0
- package/templates/native-go/backend/internal/app/routes_test.go +172 -0
- package/templates/native-go/backend/internal/dsm/auth.go +118 -0
- package/templates/native-go/backend/internal/dsm/auth_test.go +139 -0
- package/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/templates/native-go/backend/internal/helper/control.go +424 -0
- package/templates/native-go/backend/internal/helper/control_test.go +250 -0
- package/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/templates/native-go/backend/internal/helper/peer_linux.go +44 -0
- package/templates/native-go/backend/internal/helper/peer_other.go +7 -0
- package/templates/native-go/backend/internal/helper/process_linux.go +177 -0
- package/templates/native-go/backend/internal/helper/process_other.go +5 -0
- package/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/templates/native-go/backend/internal/helper/server_linux.go +124 -0
- package/templates/native-go/backend/internal/helper/status.go +334 -0
- package/templates/native-go/backend/internal/helper/status_test.go +288 -0
- package/templates/native-go/backend/internal/helper/supervision.go +107 -0
- package/templates/native-go/backend/internal/helper/supervision_test.go +124 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux.go +363 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux_test.go +913 -0
- package/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/templates/native-go/backend/internal/helper/write.go +77 -0
- package/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/templates/native-go/dsm-package.yaml +58 -0
- package/templates/native-go/gitignore +1 -0
- package/templates/native-go/i18n/glossary.json +662 -0
- package/templates/native-go/i18n/messages/de.json +28 -0
- package/templates/native-go/i18n/messages/en.json +28 -0
- package/templates/native-go/i18n/messages/es.json +28 -0
- package/templates/native-go/i18n/messages/fr.json +28 -0
- package/templates/native-go/i18n/messages/it.json +28 -0
- package/templates/native-go/i18n/messages/ja.json +28 -0
- package/templates/native-go/i18n/messages/ko.json +28 -0
- package/templates/native-go/i18n/messages/zh-CN.json +28 -0
- package/templates/native-go/i18n/messages/zh-TW.json +28 -0
- package/templates/native-go/ui/app.css +35 -0
- package/templates/native-go/ui/app.js +101 -0
- package/templates/native-go-better-auth/backend/internal/app/identity.go +208 -0
- package/templates/native-go-better-auth/backend/internal/app/identity_test.go +113 -0
- package/templates/native-go-better-auth/node/app.mjs +72 -0
- package/templates/native-go-better-auth/node/build.mjs +4 -0
- package/templates/native-go-better-auth/node/package-lock.json +862 -0
- package/templates/native-go-better-auth/node/package.json +1 -0
- package/templates/native-go-better-auth/node/test/auth.test.mjs +31 -0
- package/templates/native-go-integration/backend/internal/app/identity_none.go +6 -0
- package/templates/native-go-integration/backend/internal/app/personal.go +203 -0
- package/templates/native-go-integration/backend/internal/app/personal_test.go +119 -0
- package/templates/native-go-root/backend/internal/app/root.go +107 -0
- package/templates/native-go-root/backend/internal/app/root_test.go +124 -0
- package/templates/native-go-root/root/whoami.sh +6 -0
- package/templates/native-go-vue/README.md +224 -0
- package/templates/native-go-vue/frontend/DESIGN.md +78 -0
- package/templates/native-go-vue/frontend/package-lock.json +2410 -0
- package/templates/native-go-vue/frontend/package.json +6 -0
- package/templates/native-go-vue/frontend/src/App.vue +159 -0
- package/templates/native-go-vue/frontend/src/context.ts +56 -0
- package/templates/native-go-vue/frontend/src/main.ts +29 -0
- package/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/templates/native-go-vue/frontend/src/style.css +31 -0
- package/templates/native-go-vue/frontend/test/apps.test.ts +190 -0
- package/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/templates/native-go-vue/frontend/tsconfig.json +1 -0
- package/templates/native-go-vue/frontend/vite.config.ts +10 -0
- package/templates/native-go-vue/gitignore +2 -0
- package/dist/attestation/app-package.d.ts +0 -86
- package/dist/attestation/app-package.js +0 -206
- package/dist/attestation/install-on-host.d.ts +0 -14
- package/dist/attestation/install-on-host.js +0 -52
- package/dist/attestation/keyring.d.ts +0 -21
- package/dist/attestation/keyring.js +0 -168
- package/dist/attestation/platform-service.d.ts +0 -70
- package/dist/attestation/platform-service.js +0 -250
- package/dist/build-spk/broker-glue.d.ts +0 -16
- package/dist/build-spk/broker-glue.js +0 -40
- package/dist/deploy/catalog-publish.d.ts +0 -3
- package/dist/deploy/catalog-publish.js +0 -7
- package/dist/doctor.d.ts +0 -22
- package/dist/doctor.js +0 -822
- package/dist/error-collector.d.ts +0 -2
- package/dist/error-collector.js +0 -46
- package/dist/host/broker-paths.d.ts +0 -1
- package/dist/host/broker-paths.js +0 -1
- package/dist/host/broker-upgrade-preflight.d.ts +0 -61
- package/dist/host/broker-upgrade-preflight.js +0 -156
- package/dist/host/digests.d.ts +0 -5
- package/dist/host/digests.js +0 -63
- package/dist/host/fake-nas.d.ts +0 -49
- package/dist/host/fake-nas.js +0 -193
- package/dist/mock-broker/bootstrap.d.ts +0 -2
- package/dist/mock-broker/bootstrap.js +0 -8
- package/dist/mock-broker/files.d.ts +0 -60
- package/dist/mock-broker/files.js +0 -408
- package/dist/mock-broker/oidc.d.ts +0 -31
- package/dist/mock-broker/oidc.js +0 -161
- package/dist/mock-broker/path.d.ts +0 -9
- package/dist/mock-broker/path.js +0 -50
- package/dist/mock-broker/server.d.ts +0 -19
- package/dist/mock-broker/server.js +0 -350
- package/dist/publish/build-ledger.d.ts +0 -22
- package/dist/publish/build-ledger.js +0 -26
- package/dist/publish/community-path.d.ts +0 -6
- package/dist/publish/community-path.js +0 -41
- package/dist/publish/curated-release.d.ts +0 -78
- package/dist/publish/curated-release.js +0 -883
- package/dist/publish/file-build-ledger.d.ts +0 -18
- package/dist/publish/file-build-ledger.js +0 -268
- package/dist/publish/github-pr.d.ts +0 -25
- package/dist/publish/github-pr.js +0 -85
- package/dist/publish/github-repo.d.ts +0 -8
- package/dist/publish/github-repo.js +0 -21
- package/dist/publish/platform-service-release.d.ts +0 -60
- package/dist/publish/platform-service-release.js +0 -333
- package/dist/publish/preflight.d.ts +0 -24
- package/dist/publish/preflight.js +0 -138
- package/dist/publish/publish.d.ts +0 -27
- package/dist/publish/publish.js +0 -136
- package/dist/publish/sync-definition.d.ts +0 -4
- package/dist/publish/sync-definition.js +0 -48
- package/dist/release-bin.d.ts +0 -2
- package/dist/release-bin.js +0 -23
- package/dist/templates/hello-web/html/sdk.js +0 -68
- package/dist/templates/hello-web-page/html/sdk.js +0 -68
- package/dist/templates/native/synology-app.yaml +0 -7
- package/dist/test-host.d.ts +0 -15
- package/dist/test-host.js +0 -37
- package/templates/hello-web/html/sdk.js +0 -68
- package/templates/hello-web-page/html/sdk.js +0 -68
- package/templates/native/synology-app.yaml +0 -7
- /package/dist/templates/{native → binary}/native.yaml +0 -0
- /package/templates/{native → binary}/native.yaml +0 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"encoding/json"
|
|
6
|
+
"os"
|
|
7
|
+
"strings"
|
|
8
|
+
"sync"
|
|
9
|
+
"sync/atomic"
|
|
10
|
+
"testing"
|
|
11
|
+
"time"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
func dataFixture(t testing.TB, name string) []byte {
|
|
15
|
+
t.Helper()
|
|
16
|
+
b, err := os.ReadFile("testdata/protocol2/" + name + ".json")
|
|
17
|
+
if err != nil {
|
|
18
|
+
t.Fatal(err)
|
|
19
|
+
}
|
|
20
|
+
return b
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
func TestDataRequestFixtures(t *testing.T) {
|
|
24
|
+
for _, name := range []string{"list", "stat", "read", "create", "write-stream", "publish"} {
|
|
25
|
+
t.Run(name, func(t *testing.T) {
|
|
26
|
+
r, code := DecodeDataRequest(bytes.NewReader(dataFixture(t, name)))
|
|
27
|
+
want := Code("")
|
|
28
|
+
if name == "create" || name == "write-stream" || name == "publish" {
|
|
29
|
+
want = ErrUnsupported
|
|
30
|
+
}
|
|
31
|
+
if code != want {
|
|
32
|
+
t.Fatalf("got %q want %q", code, want)
|
|
33
|
+
}
|
|
34
|
+
if want == "" && (r.Inventory.Protocol != 2 || r.Op != Action("nas.files."+name)) {
|
|
35
|
+
t.Fatal("wrong decoded request")
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func TestPortableControlFrames(t *testing.T) {
|
|
42
|
+
var cases []struct {
|
|
43
|
+
Name string `json:"name"`
|
|
44
|
+
Frame string `json:"frame"`
|
|
45
|
+
Code Code `json:"code"`
|
|
46
|
+
}
|
|
47
|
+
if err := json.Unmarshal(dataFixture(t, "frames"), &cases); err != nil {
|
|
48
|
+
t.Fatal(err)
|
|
49
|
+
}
|
|
50
|
+
for _, tc := range cases {
|
|
51
|
+
t.Run(tc.Name, func(t *testing.T) {
|
|
52
|
+
_, code := DecodeDataRequest(strings.NewReader(tc.Frame))
|
|
53
|
+
if code != tc.Code {
|
|
54
|
+
t.Fatalf("got %q want %q", code, tc.Code)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func TestTicketBindsArgumentsAndCurrentEpoch(t *testing.T) {
|
|
61
|
+
r, b, now := validRequestAndTicket(t)
|
|
62
|
+
w, _ := NewReplayWindow(r.Inventory, r.Epoch, b.SubjectRef, b.SessionRef)
|
|
63
|
+
changed := r
|
|
64
|
+
changed.Args = bytes.Replace(r.Args, []byte("note.txt"), []byte("other.txt"), 1)
|
|
65
|
+
if c := w.Consume(changed, b, now); c != ErrDenied {
|
|
66
|
+
t.Fatal("ticket substituted args", c)
|
|
67
|
+
}
|
|
68
|
+
changed = r
|
|
69
|
+
changed.Epoch = strings.Repeat("0", 64)
|
|
70
|
+
if c := w.Consume(changed, b, now); c != ErrStale {
|
|
71
|
+
t.Fatal("old/new epoch accepted", c)
|
|
72
|
+
}
|
|
73
|
+
changed = r
|
|
74
|
+
changed.Inventory.RegistryDigest = strings.Repeat("0", 64)
|
|
75
|
+
if c := w.Consume(changed, b, now); c != ErrIncompatible {
|
|
76
|
+
t.Fatal("inventory changed", c)
|
|
77
|
+
}
|
|
78
|
+
if c := w.Consume(r, b, now); c != "" {
|
|
79
|
+
t.Fatal("invalid request burned valid ticket", c)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func TestRequiredFieldsAndStagedWrites(t *testing.T) {
|
|
84
|
+
b := dataFixture(t, "create")
|
|
85
|
+
var fields map[string]json.RawMessage
|
|
86
|
+
if err := json.Unmarshal(b, &fields); err != nil {
|
|
87
|
+
t.Fatal(err)
|
|
88
|
+
}
|
|
89
|
+
var args map[string]json.RawMessage
|
|
90
|
+
if err := json.Unmarshal(fields["args"], &args); err != nil {
|
|
91
|
+
t.Fatal(err)
|
|
92
|
+
}
|
|
93
|
+
delete(args, "bytes")
|
|
94
|
+
fields["args"], _ = json.Marshal(args)
|
|
95
|
+
raw, _ := json.Marshal(fields)
|
|
96
|
+
if _, c := DecodeDataRequest(bytes.NewReader(raw)); c != ErrInvalid {
|
|
97
|
+
t.Fatal("missing zero-valued required field accepted", c)
|
|
98
|
+
}
|
|
99
|
+
for _, pair := range []struct{ from, to string }{
|
|
100
|
+
{`"exclusive": true`, `"exclusive": false`},
|
|
101
|
+
{`"bytes":`, `"data":"base64","bytes":`},
|
|
102
|
+
} {
|
|
103
|
+
if _, c := DecodeDataRequest(bytes.NewReader(bytes.Replace(b, []byte(pair.from), []byte(pair.to), 1))); c != ErrInvalid {
|
|
104
|
+
t.Fatal(pair, c)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func TestGrantStoreLimitsAndTombstones(t *testing.T) {
|
|
110
|
+
s, c := DecodeGrantStore(bytes.NewReader(dataFixture(t, "grant-store")))
|
|
111
|
+
if c != "" {
|
|
112
|
+
t.Fatal(c)
|
|
113
|
+
}
|
|
114
|
+
encode := func(s GrantStore) Code {
|
|
115
|
+
b, err := json.Marshal(s)
|
|
116
|
+
if err != nil {
|
|
117
|
+
t.Fatal(err)
|
|
118
|
+
}
|
|
119
|
+
_, c := DecodeGrantStore(bytes.NewReader(b))
|
|
120
|
+
return c
|
|
121
|
+
}
|
|
122
|
+
g := s.Grants[0]
|
|
123
|
+
g.State = GrantSuspended
|
|
124
|
+
g.Reason = ErrSuspended
|
|
125
|
+
s.Grants[0] = g
|
|
126
|
+
if c := encode(s); c != "" {
|
|
127
|
+
t.Fatal("suspension record", c)
|
|
128
|
+
}
|
|
129
|
+
g.State = GrantRevoked
|
|
130
|
+
g.Reason = ErrRevoked
|
|
131
|
+
g.RevokedAt = g.CreatedAt
|
|
132
|
+
s.Grants[0] = g
|
|
133
|
+
if c := encode(s); c != "" {
|
|
134
|
+
t.Fatal("tombstone record", c)
|
|
135
|
+
}
|
|
136
|
+
s.Grants = append(s.Grants, g)
|
|
137
|
+
if c := encode(s); c != ErrInvalid {
|
|
138
|
+
t.Fatal("duplicate ID accepted", c)
|
|
139
|
+
}
|
|
140
|
+
s.Grants = make([]Grant, MaxGrants)
|
|
141
|
+
for n := range s.Grants {
|
|
142
|
+
g.ID = strings.Repeat("0", 60) + hex4(n)
|
|
143
|
+
s.Grants[n] = g
|
|
144
|
+
}
|
|
145
|
+
if c := encode(s); c != "" {
|
|
146
|
+
t.Fatal("capacity boundary", c)
|
|
147
|
+
}
|
|
148
|
+
s.Grants = append(s.Grants, g)
|
|
149
|
+
if c := encode(s); c != ErrLimit {
|
|
150
|
+
t.Fatal("capacity including tombstones", c)
|
|
151
|
+
}
|
|
152
|
+
s.Grants = []Grant{g}
|
|
153
|
+
s.Grants[0].Issuer.SubjectRef = strings.Repeat("0", 64)
|
|
154
|
+
if c := encode(s); c != ErrDenied {
|
|
155
|
+
t.Fatal("admin cannot issue personal grant for another owner", c)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
func TestStrictUnicodeAndDepth(t *testing.T) {
|
|
160
|
+
b := string(dataFixture(t, "read"))
|
|
161
|
+
for _, name := range []string{`\ud83d\ude00`, `\uFFFD`, `a\"b`, `a\\b`} {
|
|
162
|
+
_, c := DecodeDataRequest(strings.NewReader(strings.Replace(b, "note.txt", name, 1)))
|
|
163
|
+
// A literal backslash in a segment is outside this contract's subset.
|
|
164
|
+
want := Code("")
|
|
165
|
+
if name == `a\\b` {
|
|
166
|
+
want = ErrInvalid
|
|
167
|
+
}
|
|
168
|
+
if c != want {
|
|
169
|
+
t.Fatalf("%s: %q", name, c)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
deep := strings.Repeat(`{"x":`, 65) + `0` + strings.Repeat(`}`, 65)
|
|
173
|
+
var value DataRequest
|
|
174
|
+
if c := decodeDataObject(strings.NewReader(strings.Replace(b, `"args": {`, `"args": `+deep+`,"removed": {`, 1)), &value, MaxControlBytes); c != ErrInvalid {
|
|
175
|
+
t.Fatal("depth accepted", c)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
func TestDataStrictFrames(t *testing.T) {
|
|
180
|
+
b := string(dataFixture(t, "read"))
|
|
181
|
+
cases := []struct {
|
|
182
|
+
name, data string
|
|
183
|
+
code Code
|
|
184
|
+
}{
|
|
185
|
+
{"unknown root", strings.Replace(b, `"args":`, `"uid":0,"args":`, 1), ErrInvalid},
|
|
186
|
+
{"unknown inventory", strings.Replace(b, `"package":`, `"admin":true,"package":`, 1), ErrInvalid},
|
|
187
|
+
{"unknown args", strings.Replace(b, `"maxBytes":`, `"offset":0,"maxBytes":`, 1), ErrInvalid},
|
|
188
|
+
{"case alias", strings.Replace(b, `"nonce":`, `"Nonce":`, 1), ErrInvalid},
|
|
189
|
+
{"duplicate root", strings.Replace(b, `"nonce":`, `"nonce":"x","nonce":`, 1), ErrInvalid},
|
|
190
|
+
{"duplicate nested", strings.Replace(b, `"segments":`, `"segments":[],"segments":`, 1), ErrInvalid},
|
|
191
|
+
{"trailing object", b + `{}`, ErrInvalid},
|
|
192
|
+
{"trailing junk", b + `x`, ErrInvalid},
|
|
193
|
+
{"oversized whitespace", b + strings.Repeat(" ", MaxControlBytes), ErrLimit},
|
|
194
|
+
{"missing ticket", strings.Replace(b, `"ticket":`, `"missingTicket":`, 1), ErrInvalid},
|
|
195
|
+
{"null args", strings.Replace(b, `"args": {`, `"args": null,"removed": {`, 1), ErrInvalid},
|
|
196
|
+
{"null segments", strings.Replace(b, "[\n \"note.txt\"\n ]", "null", 1), ErrInvalid},
|
|
197
|
+
{"wrong scalar", strings.Replace(b, `"grantRevision": 1`, `"grantRevision": "1"`, 1), ErrInvalid},
|
|
198
|
+
{"zero revision", strings.Replace(b, `"grantRevision": 1`, `"grantRevision": 0`, 1), ErrInvalid},
|
|
199
|
+
{"unknown op", strings.Replace(b, `nas.files.read`, `shell`, 1), ErrUnsupported},
|
|
200
|
+
{"protocol downgrade", strings.Replace(b, `"protocol": 2`, `"protocol": 1`, 1), ErrIncompatible},
|
|
201
|
+
{"future protocol", strings.Replace(b, `"protocol": 2`, `"protocol": 3`, 1), ErrIncompatible},
|
|
202
|
+
{"absolute path", strings.Replace(b, `note.txt`, `/etc/shadow`, 1), ErrInvalid},
|
|
203
|
+
{"parent traversal", strings.Replace(b, `note.txt`, `..`, 1), ErrInvalid},
|
|
204
|
+
{"surrogate", strings.Replace(b, `note.txt`, `\ud800`, 1), ErrInvalid},
|
|
205
|
+
{"invalid UTF8", strings.Replace(b, `note.txt`, string([]byte{0xff}), 1), ErrInvalid},
|
|
206
|
+
{"null envelope", `null`, ErrInvalid},
|
|
207
|
+
{"limit overflow", strings.Replace(b, `1048576`, `18446744073709551616`, 1), ErrInvalid},
|
|
208
|
+
{"over read limit", strings.Replace(b, `1048576`, `1048577`, 1), ErrLimit},
|
|
209
|
+
}
|
|
210
|
+
for _, tc := range cases {
|
|
211
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
212
|
+
_, got := DecodeDataRequest(strings.NewReader(tc.data))
|
|
213
|
+
if got != tc.code {
|
|
214
|
+
t.Fatalf("got %q want %q", got, tc.code)
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
func TestRelativeSegmentsContract(t *testing.T) {
|
|
221
|
+
for _, s := range [][]string{{".."}, {"."}, {""}, {"a/b"}, {"/x"}, {"x\x00y"}, {"a\\b"}, {strings.Repeat("a", 256)}, nil} {
|
|
222
|
+
if ValidateRelativeSegments(s, true) == "" {
|
|
223
|
+
t.Fatalf("accepted %q", s)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if ValidateRelativeSegments([]string{}, true) != "" || ValidateRelativeSegments([]string{}, false) != ErrInvalid {
|
|
227
|
+
t.Fatal("root rules")
|
|
228
|
+
}
|
|
229
|
+
if ValidateRelativeSegments([]string{"\u8cc7\u6599\u593e", "%2e%2e", "a%2fb", "é", "e\u0301"}, false) != "" {
|
|
230
|
+
t.Fatal("literal UTF8/percent must not be normalized or URL-decoded again")
|
|
231
|
+
}
|
|
232
|
+
if ValidateRelativeSegments(make([]string, MaxPathSegments+1), true) != ErrLimit {
|
|
233
|
+
t.Fatal("depth ceiling")
|
|
234
|
+
}
|
|
235
|
+
segments := make([]string, 17)
|
|
236
|
+
for i := range segments {
|
|
237
|
+
segments[i] = strings.Repeat("a", 255)
|
|
238
|
+
}
|
|
239
|
+
if ValidateRelativeSegments(segments, true) != ErrLimit {
|
|
240
|
+
t.Fatal("byte ceiling")
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
func TestProtocolNegotiationPinnedToApproval(t *testing.T) {
|
|
245
|
+
i := fixture(t).Expected
|
|
246
|
+
for _, tc := range []struct {
|
|
247
|
+
offered []int
|
|
248
|
+
approved, want int
|
|
249
|
+
files bool
|
|
250
|
+
code Code
|
|
251
|
+
}{
|
|
252
|
+
{[]int{1, 2}, 1, 1, false, ""}, {[]int{1, 2}, 2, 2, true, ""},
|
|
253
|
+
{[]int{1}, 2, 0, false, ErrIncompatible}, {[]int{2}, 1, 0, false, ErrIncompatible},
|
|
254
|
+
{[]int{1, 2}, 1, 0, true, ErrIncompatible}, {[]int{1, 2, 3}, 2, 0, true, ErrInvalid},
|
|
255
|
+
{[]int{3}, 2, 0, true, ErrIncompatible},
|
|
256
|
+
{[]int{2, 2}, 2, 0, true, ErrInvalid}, {nil, 2, 0, true, ErrInvalid},
|
|
257
|
+
} {
|
|
258
|
+
i.Protocol = tc.approved
|
|
259
|
+
got, code := NegotiateProtocol(tc.offered, i, tc.files)
|
|
260
|
+
if got != tc.want || code != tc.code {
|
|
261
|
+
t.Fatalf("%+v: %d %q", tc, got, code)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
i.Protocol = 1
|
|
265
|
+
if Respond(i, false, Request{i, "nas.files.read", strings.Repeat("a", 64)}).Error != "unsupported" {
|
|
266
|
+
t.Fatal("legacy must never serve files")
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
func validRequestAndTicket(t *testing.T) (DataRequest, TicketBinding, time.Time) {
|
|
271
|
+
t.Helper()
|
|
272
|
+
r, code := DecodeDataRequest(bytes.NewReader(dataFixture(t, "read")))
|
|
273
|
+
if code != "" {
|
|
274
|
+
t.Fatal(code)
|
|
275
|
+
}
|
|
276
|
+
now := time.Unix(1791000000, 0)
|
|
277
|
+
b := TicketBinding{Inventory: r.Inventory, Epoch: r.Epoch, SubjectRef: strings.Repeat("3", 64), SessionRef: strings.Repeat("4", 64), Action: r.Op, GrantID: r.GrantID, GrantRevision: r.GrantRevision, OperationID: r.OperationID, Nonce: r.Nonce, Ticket: r.Ticket, RequestDigest: r.Digest(), ExpiresAt: now.Add(time.Second)}
|
|
278
|
+
return r, b, now
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
func TestRequestReplayAndBinding(t *testing.T) {
|
|
282
|
+
r, b, now := validRequestAndTicket(t)
|
|
283
|
+
newWindow := func() *ReplayWindow {
|
|
284
|
+
w, c := NewReplayWindow(r.Inventory, r.Epoch, b.SubjectRef, b.SessionRef)
|
|
285
|
+
if c != "" {
|
|
286
|
+
t.Fatal(c)
|
|
287
|
+
}
|
|
288
|
+
return w
|
|
289
|
+
}
|
|
290
|
+
for _, change := range []string{"inventory", "epoch", "subject", "session", "action", "grant", "revision", "operation", "nonce", "ticket", "expiry"} {
|
|
291
|
+
t.Run(change, func(t *testing.T) {
|
|
292
|
+
bad := b
|
|
293
|
+
switch change {
|
|
294
|
+
case "inventory":
|
|
295
|
+
bad.Inventory.PayloadDigest = strings.Repeat("0", 64)
|
|
296
|
+
case "epoch":
|
|
297
|
+
bad.Epoch = strings.Repeat("0", 64)
|
|
298
|
+
case "subject":
|
|
299
|
+
bad.SubjectRef = strings.Repeat("0", 64)
|
|
300
|
+
case "session":
|
|
301
|
+
bad.SessionRef = strings.Repeat("0", 64)
|
|
302
|
+
case "action":
|
|
303
|
+
bad.Action = ActionStat
|
|
304
|
+
case "grant":
|
|
305
|
+
bad.GrantID = strings.Repeat("0", 64)
|
|
306
|
+
case "revision":
|
|
307
|
+
bad.GrantRevision++
|
|
308
|
+
case "operation":
|
|
309
|
+
bad.OperationID = strings.Repeat("0", 64)
|
|
310
|
+
case "nonce":
|
|
311
|
+
bad.Nonce = strings.Repeat("0", 64)
|
|
312
|
+
case "ticket":
|
|
313
|
+
bad.Ticket = strings.Repeat("0", 64)
|
|
314
|
+
case "expiry":
|
|
315
|
+
bad.ExpiresAt = now
|
|
316
|
+
}
|
|
317
|
+
w := newWindow()
|
|
318
|
+
if w.Consume(r, bad, now) == "" {
|
|
319
|
+
t.Fatal("binding accepted")
|
|
320
|
+
}
|
|
321
|
+
if c := w.Consume(r, b, now); c != "" {
|
|
322
|
+
t.Fatalf("failed binding consumed valid request: %q", c)
|
|
323
|
+
}
|
|
324
|
+
})
|
|
325
|
+
}
|
|
326
|
+
w := newWindow()
|
|
327
|
+
if c := w.Consume(r, b, now); c != "" {
|
|
328
|
+
t.Fatal(c)
|
|
329
|
+
}
|
|
330
|
+
if c := w.Consume(r, b, now); c != ErrReplay {
|
|
331
|
+
t.Fatal(c)
|
|
332
|
+
}
|
|
333
|
+
for _, duplicate := range []string{"nonce", "operation", "ticket"} {
|
|
334
|
+
r2, b2 := r, b
|
|
335
|
+
r2.Nonce = strings.Repeat("5", 64)
|
|
336
|
+
r2.OperationID = strings.Repeat("6", 64)
|
|
337
|
+
r2.Ticket = strings.Repeat("7", 64)
|
|
338
|
+
switch duplicate {
|
|
339
|
+
case "nonce":
|
|
340
|
+
r2.Nonce = r.Nonce
|
|
341
|
+
case "operation":
|
|
342
|
+
r2.OperationID = r.OperationID
|
|
343
|
+
case "ticket":
|
|
344
|
+
r2.Ticket = r.Ticket
|
|
345
|
+
}
|
|
346
|
+
b2.Nonce = r2.Nonce
|
|
347
|
+
b2.OperationID = r2.OperationID
|
|
348
|
+
b2.Ticket = r2.Ticket
|
|
349
|
+
b2.RequestDigest = r2.Digest()
|
|
350
|
+
if c := w.Consume(r2, b2, now); c != ErrReplay {
|
|
351
|
+
t.Fatalf("%s replay: %q", duplicate, c)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
func TestReplayConcurrentAndFull(t *testing.T) {
|
|
357
|
+
r, b, now := validRequestAndTicket(t)
|
|
358
|
+
w, _ := NewReplayWindow(r.Inventory, r.Epoch, b.SubjectRef, b.SessionRef)
|
|
359
|
+
var accepted atomic.Int32
|
|
360
|
+
var wg sync.WaitGroup
|
|
361
|
+
for n := 0; n < 20; n++ {
|
|
362
|
+
wg.Add(1)
|
|
363
|
+
go func() {
|
|
364
|
+
defer wg.Done()
|
|
365
|
+
if w.Consume(r, b, now) == "" {
|
|
366
|
+
accepted.Add(1)
|
|
367
|
+
}
|
|
368
|
+
}()
|
|
369
|
+
}
|
|
370
|
+
wg.Wait()
|
|
371
|
+
if accepted.Load() != 1 {
|
|
372
|
+
t.Fatal("single-use must be atomic")
|
|
373
|
+
}
|
|
374
|
+
for n := 1; n < MaxReplayEntries; n++ {
|
|
375
|
+
x := strings.Repeat("0", 60) + hex4(n)
|
|
376
|
+
r.Nonce = x
|
|
377
|
+
r.OperationID = x
|
|
378
|
+
r.Ticket = x
|
|
379
|
+
b.Nonce = x
|
|
380
|
+
b.OperationID = x
|
|
381
|
+
b.Ticket = x
|
|
382
|
+
b.RequestDigest = r.Digest()
|
|
383
|
+
if c := w.Consume(r, b, now); c != "" {
|
|
384
|
+
t.Fatal(c)
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
r.Nonce = strings.Repeat("9", 64)
|
|
388
|
+
r.OperationID = r.Nonce
|
|
389
|
+
r.Ticket = r.Nonce
|
|
390
|
+
b.Nonce = r.Nonce
|
|
391
|
+
b.OperationID = r.Nonce
|
|
392
|
+
b.Ticket = r.Nonce
|
|
393
|
+
b.RequestDigest = r.Digest()
|
|
394
|
+
if c := w.Consume(r, b, now); c != ErrBusy {
|
|
395
|
+
t.Fatal("full must not evict", c)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
func hex4(n int) string {
|
|
400
|
+
const chars = "0123456789abcdef"
|
|
401
|
+
return string([]byte{chars[(n>>12)&15], chars[(n>>8)&15], chars[(n>>4)&15], chars[n&15]})
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
func TestGrantAndIntentStrictRecords(t *testing.T) {
|
|
405
|
+
g := dataFixture(t, "grant-store")
|
|
406
|
+
if s, c := DecodeGrantStore(bytes.NewReader(g)); c != "" || len(s.Grants) != 1 {
|
|
407
|
+
t.Fatal(c)
|
|
408
|
+
}
|
|
409
|
+
i := dataFixture(t, "intent")
|
|
410
|
+
if _, c := DecodeIntent(bytes.NewReader(i)); c != "" {
|
|
411
|
+
t.Fatal(c)
|
|
412
|
+
}
|
|
413
|
+
for _, change := range []struct{ from, to string }{
|
|
414
|
+
{`"grantSchema": 1`, `"grantSchema": 2`}, {`"kind": "local"`, `"kind": "ldap"`},
|
|
415
|
+
{`"targetKind": "directory"`, `"targetKind": "file"`}, {`"state": "active"`, `"state": "unknown"`},
|
|
416
|
+
{`"mountRef":`, `"path":"/secret","mountRef":`}, {`nas.files.read`, `shell`},
|
|
417
|
+
{`"segments":`, `"Segments":`}, {`"grantRevision": 1`, `"grantRevision": 0`},
|
|
418
|
+
} {
|
|
419
|
+
if _, c := DecodeGrantStore(bytes.NewReader(bytes.Replace(g, []byte(change.from), []byte(change.to), 1))); c == "" {
|
|
420
|
+
t.Fatalf("accepted %+v", change)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if _, c := DecodeIntent(bytes.NewReader(bytes.Replace(i, []byte(`"summaryDigest":`), []byte(`"admin":true,"summaryDigest":`), 1))); c != ErrInvalid {
|
|
424
|
+
t.Fatal(c)
|
|
425
|
+
}
|
|
426
|
+
if _, c := DecodeGrantStore(strings.NewReader(string(g) + strings.Repeat(" ", MaxGrantStoreBytes))); c != ErrLimit {
|
|
427
|
+
t.Fatal(c)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
func TestSafeErrorCannotLeakUnknownCode(t *testing.T) {
|
|
432
|
+
b, err := json.Marshal(SafeError{Code: Code("/secret/path credential=oops"), OperationID: "/secret"})
|
|
433
|
+
if err != nil || strings.Contains(string(b), "secret") || !strings.Contains(string(b), "internal") {
|
|
434
|
+
t.Fatalf("%s %v", b, err)
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
func FuzzDataDecoder(f *testing.F) {
|
|
439
|
+
for _, name := range []string{"list", "stat", "read", "create"} {
|
|
440
|
+
f.Add(dataFixture(f, name))
|
|
441
|
+
}
|
|
442
|
+
f.Add([]byte(`{"args":{"x":{"x":{"x":null}}}}`))
|
|
443
|
+
f.Fuzz(func(t *testing.T, b []byte) {
|
|
444
|
+
_, c := DecodeDataRequest(bytes.NewReader(b))
|
|
445
|
+
if c != "" && !c.Valid() {
|
|
446
|
+
t.Fatalf("unsafe code %q", c)
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"golang.org/x/sys/unix"
|
|
6
|
+
"os"
|
|
7
|
+
"runtime"
|
|
8
|
+
"slices"
|
|
9
|
+
"strconv"
|
|
10
|
+
"time"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
// EA masks from DSM7-4 libsynoacl and syno_acl_xattr_ds.h. A bridge must prove
|
|
14
|
+
// target support and action semantics; unsupported never falls back to POSIX.
|
|
15
|
+
const (
|
|
16
|
+
nativeACLExec uint32 = 0x0001
|
|
17
|
+
nativeACLRead uint32 = 0x0004
|
|
18
|
+
nativeACLReadAttr uint32 = 0x0100
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
type nativeFDACLObservation struct {
|
|
22
|
+
FilesystemSupported, ObjectSupported, MasksVerified, Allowed bool
|
|
23
|
+
CheckedAt time.Time
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Check runs IN the permanently dropped operation process, not a CLI subprocess.
|
|
27
|
+
// fd/alias are generated by this adapter, never received from caller controls.
|
|
28
|
+
type fixedFDACLBridge interface {
|
|
29
|
+
Check(context.Context, int, string, uint32) (nativeFDACLObservation, Code)
|
|
30
|
+
}
|
|
31
|
+
type fixedFDNativeACL struct {
|
|
32
|
+
actor NativeActor
|
|
33
|
+
native fixedFDACLBridge
|
|
34
|
+
boundary readOnlyACL
|
|
35
|
+
now func() time.Time
|
|
36
|
+
credentials func(NativeActor) Code
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func newFixedFDNativeACL(a NativeActor, n fixedFDACLBridge, b readOnlyACL) *fixedFDNativeACL {
|
|
40
|
+
return &fixedFDNativeACL{actor: a, native: n, boundary: b, now: time.Now, credentials: fixedFDActorCredentials}
|
|
41
|
+
}
|
|
42
|
+
func fixedFDActorCredentials(a NativeActor) Code {
|
|
43
|
+
if !a.valid || a.UID() == 0 {
|
|
44
|
+
return ErrDenied
|
|
45
|
+
}
|
|
46
|
+
ru, eu, su := unix.Getresuid()
|
|
47
|
+
rg, eg, sg := unix.Getresgid()
|
|
48
|
+
groups, err := os.Getgroups()
|
|
49
|
+
want := []int{}
|
|
50
|
+
for _, g := range a.Groups() {
|
|
51
|
+
want = append(want, int(g))
|
|
52
|
+
}
|
|
53
|
+
slices.Sort(groups)
|
|
54
|
+
slices.Sort(want)
|
|
55
|
+
if err != nil || ru != int(a.UID()) || eu != ru || su != ru || rg != int(a.GID()) || eg != rg || sg != rg || !slices.Equal(groups, want) {
|
|
56
|
+
return ErrDenied
|
|
57
|
+
}
|
|
58
|
+
var caps [2]unix.CapUserData
|
|
59
|
+
h := unix.CapUserHeader{Version: unix.LINUX_CAPABILITY_VERSION_3}
|
|
60
|
+
if unix.Capget(&h, &caps[0]) != nil || caps[0] != (unix.CapUserData{}) || caps[1] != (unix.CapUserData{}) {
|
|
61
|
+
return ErrDenied
|
|
62
|
+
}
|
|
63
|
+
dump, e := unix.PrctlRetInt(unix.PR_GET_DUMPABLE, 0, 0, 0, 0)
|
|
64
|
+
if e != nil || dump != 0 {
|
|
65
|
+
return ErrDenied
|
|
66
|
+
}
|
|
67
|
+
priv, e := unix.PrctlRetInt(unix.PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0)
|
|
68
|
+
if e != nil || priv != 1 {
|
|
69
|
+
return ErrDenied
|
|
70
|
+
}
|
|
71
|
+
return ""
|
|
72
|
+
}
|
|
73
|
+
func (a *fixedFDNativeACL) Authorize(ctx context.Context, action Action, fd int) Code {
|
|
74
|
+
if a == nil || a.native == nil || a.boundary == nil || a.now == nil || a.credentials == nil {
|
|
75
|
+
return ErrUnsupported
|
|
76
|
+
}
|
|
77
|
+
if !action.ReadOnly() {
|
|
78
|
+
return ErrUnsupported
|
|
79
|
+
}
|
|
80
|
+
runtime.LockOSThread()
|
|
81
|
+
defer runtime.UnlockOSThread()
|
|
82
|
+
if !a.actor.valid || !nativeFresh(a.actor.account.CheckedAt, a.now()) {
|
|
83
|
+
return ErrStale
|
|
84
|
+
}
|
|
85
|
+
ctx, cancel := context.WithTimeout(ctx, NativeProofFreshness)
|
|
86
|
+
defer cancel()
|
|
87
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
88
|
+
return c
|
|
89
|
+
}
|
|
90
|
+
if c := a.credentials(a.actor); c != "" {
|
|
91
|
+
return safeGrantCode(c)
|
|
92
|
+
}
|
|
93
|
+
duplicate, err := unix.FcntlInt(uintptr(fd), unix.F_DUPFD_CLOEXEC, 3)
|
|
94
|
+
if err != nil {
|
|
95
|
+
return ErrUnavailable
|
|
96
|
+
}
|
|
97
|
+
defer unix.Close(duplicate)
|
|
98
|
+
var st unix.Stat_t
|
|
99
|
+
if c := readOnlyInspect(duplicate, &st); c != "" {
|
|
100
|
+
return c
|
|
101
|
+
}
|
|
102
|
+
if c := nativeObservationCode(ctx, a.boundary.Authorize(ctx, action, duplicate)); c != "" {
|
|
103
|
+
return c
|
|
104
|
+
}
|
|
105
|
+
mask := nativeACLRead | nativeACLReadAttr
|
|
106
|
+
if st.Mode&unix.S_IFMT == unix.S_IFDIR {
|
|
107
|
+
mask |= nativeACLExec
|
|
108
|
+
}
|
|
109
|
+
o, c := a.native.Check(ctx, duplicate, "/proc/self/fd/"+strconv.Itoa(duplicate), mask)
|
|
110
|
+
if c = nativeObservationCode(ctx, c); c != "" {
|
|
111
|
+
return c
|
|
112
|
+
}
|
|
113
|
+
if !o.FilesystemSupported || !o.ObjectSupported || !o.MasksVerified {
|
|
114
|
+
return ErrUnsupported
|
|
115
|
+
}
|
|
116
|
+
if !o.Allowed {
|
|
117
|
+
return ErrDenied
|
|
118
|
+
}
|
|
119
|
+
if !nativeFresh(o.CheckedAt, a.now()) {
|
|
120
|
+
return ErrStale
|
|
121
|
+
}
|
|
122
|
+
if c = a.credentials(a.actor); c != "" {
|
|
123
|
+
return safeGrantCode(c)
|
|
124
|
+
}
|
|
125
|
+
var after unix.Stat_t
|
|
126
|
+
if c = readOnlyInspect(duplicate, &after); c != "" {
|
|
127
|
+
return c
|
|
128
|
+
}
|
|
129
|
+
if !sameReadOnlyObject(st, after) {
|
|
130
|
+
return ErrStale
|
|
131
|
+
}
|
|
132
|
+
if c = nativeObservationCode(ctx, a.boundary.Authorize(ctx, action, duplicate)); c != "" {
|
|
133
|
+
return c
|
|
134
|
+
}
|
|
135
|
+
if !nativeFresh(o.CheckedAt, a.now()) || !nativeFresh(a.actor.account.CheckedAt, a.now()) {
|
|
136
|
+
return ErrStale
|
|
137
|
+
}
|
|
138
|
+
return ""
|
|
139
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"golang.org/x/sys/unix"
|
|
6
|
+
"os"
|
|
7
|
+
"strconv"
|
|
8
|
+
"testing"
|
|
9
|
+
"time"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
type aclNativeFake struct {
|
|
13
|
+
value nativeFDACLObservation
|
|
14
|
+
code Code
|
|
15
|
+
calls int
|
|
16
|
+
alias string
|
|
17
|
+
mask uint32
|
|
18
|
+
expected uint64
|
|
19
|
+
rename func()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
func (f *aclNativeFake) Check(ctx context.Context, fd int, alias string, mask uint32) (nativeFDACLObservation, Code) {
|
|
23
|
+
f.calls++
|
|
24
|
+
f.alias = alias
|
|
25
|
+
f.mask = mask
|
|
26
|
+
var st unix.Stat_t
|
|
27
|
+
if unix.Fstat(fd, &st) != nil || st.Ino != f.expected {
|
|
28
|
+
return nativeFDACLObservation{}, ErrDenied
|
|
29
|
+
}
|
|
30
|
+
if alias != "/proc/self/fd/"+strconv.Itoa(fd) {
|
|
31
|
+
return nativeFDACLObservation{}, ErrDenied
|
|
32
|
+
}
|
|
33
|
+
if f.rename != nil {
|
|
34
|
+
f.rename()
|
|
35
|
+
}
|
|
36
|
+
return f.value, f.code
|
|
37
|
+
}
|
|
38
|
+
func TestDSMFixedFDACLUsesPinnedObjectAndNativeSupport(t *testing.T) {
|
|
39
|
+
p, _, _, c, now := nativeFixture()
|
|
40
|
+
actor, _ := p.Resolve(context.Background(), c)
|
|
41
|
+
root := t.TempDir()
|
|
42
|
+
os.WriteFile(root+"/file", []byte("private"), 0600)
|
|
43
|
+
file, err := os.Open(root + "/file")
|
|
44
|
+
if err != nil {
|
|
45
|
+
t.Fatal(err)
|
|
46
|
+
}
|
|
47
|
+
defer file.Close()
|
|
48
|
+
var st unix.Stat_t
|
|
49
|
+
unix.Fstat(int(file.Fd()), &st)
|
|
50
|
+
f := &aclNativeFake{expected: st.Ino, value: nativeFDACLObservation{FilesystemSupported: true, ObjectSupported: true, MasksVerified: true, Allowed: true, CheckedAt: now}}
|
|
51
|
+
a := newFixedFDNativeACL(actor, f, fixtureReadOnlyACL{})
|
|
52
|
+
a.now = func() time.Time { return now }
|
|
53
|
+
a.credentials = func(NativeActor) Code { return "" }
|
|
54
|
+
f.rename = func() {
|
|
55
|
+
f.rename = nil
|
|
56
|
+
os.Rename(root+"/file", root+"/old")
|
|
57
|
+
os.WriteFile(root+"/file", []byte("replacement"), 0600)
|
|
58
|
+
}
|
|
59
|
+
if code := a.Authorize(context.Background(), ActionRead, int(file.Fd())); code != "" || f.calls != 1 || f.mask != nativeACLRead|nativeACLReadAttr {
|
|
60
|
+
t.Fatal(code, f.mask)
|
|
61
|
+
}
|
|
62
|
+
for _, change := range []func(*nativeFDACLObservation){func(o *nativeFDACLObservation) { o.FilesystemSupported = false }, func(o *nativeFDACLObservation) { o.ObjectSupported = false }, func(o *nativeFDACLObservation) { o.MasksVerified = false }, func(o *nativeFDACLObservation) { o.Allowed = false }, func(o *nativeFDACLObservation) { o.CheckedAt = time.Time{} }} {
|
|
63
|
+
f.value = nativeFDACLObservation{FilesystemSupported: true, ObjectSupported: true, MasksVerified: true, Allowed: true, CheckedAt: now}
|
|
64
|
+
change(&f.value)
|
|
65
|
+
if code := a.Authorize(context.Background(), ActionRead, int(file.Fd())); code == "" {
|
|
66
|
+
t.Fatal("unproved native Allow")
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
a.credentials = func(NativeActor) Code { return ErrDenied }
|
|
70
|
+
before := f.calls
|
|
71
|
+
if code := a.Authorize(context.Background(), ActionRead, int(file.Fd())); code != ErrDenied || f.calls != before {
|
|
72
|
+
t.Fatal("root/stale credential reached ACL", code)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
func TestDSMFixedFDACLNoNativeOrBoundaryFallback(t *testing.T) {
|
|
76
|
+
p, _, _, c, _ := nativeFixture()
|
|
77
|
+
actor, _ := p.Resolve(context.Background(), c)
|
|
78
|
+
for _, a := range []*fixedFDNativeACL{newFixedFDNativeACL(actor, nil, fixtureReadOnlyACL{}), newFixedFDNativeACL(actor, &aclNativeFake{}, nil)} {
|
|
79
|
+
if code := a.Authorize(context.Background(), ActionStat, 0); code == "" {
|
|
80
|
+
t.Fatal("missing gate allowed")
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// A successful final boundary check must not publish expired native/actor proof.
|
|
86
|
+
type agingACLBoundary struct {
|
|
87
|
+
calls int
|
|
88
|
+
advance func()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func (b *agingACLBoundary) Authorize(context.Context, Action, int) Code {
|
|
92
|
+
b.calls++
|
|
93
|
+
if b.calls == 2 {
|
|
94
|
+
b.advance()
|
|
95
|
+
}
|
|
96
|
+
return ""
|
|
97
|
+
}
|
|
98
|
+
func TestDSMFixedFDACLFinalBoundaryCannotPublishExpiredProof(t *testing.T) {
|
|
99
|
+
p, _, _, carriers, now := nativeFixture()
|
|
100
|
+
actor, code := p.Resolve(context.Background(), carriers)
|
|
101
|
+
if code != "" {
|
|
102
|
+
t.Fatal(code)
|
|
103
|
+
}
|
|
104
|
+
file, err := os.CreateTemp(t.TempDir(), "pinned")
|
|
105
|
+
if err != nil {
|
|
106
|
+
t.Fatal(err)
|
|
107
|
+
}
|
|
108
|
+
defer file.Close()
|
|
109
|
+
var st unix.Stat_t
|
|
110
|
+
if err := unix.Fstat(int(file.Fd()), &st); err != nil {
|
|
111
|
+
t.Fatal(err)
|
|
112
|
+
}
|
|
113
|
+
native := &aclNativeFake{expected: st.Ino, value: nativeFDACLObservation{FilesystemSupported: true, ObjectSupported: true, MasksVerified: true, Allowed: true, CheckedAt: now}}
|
|
114
|
+
boundary := &agingACLBoundary{advance: func() { now = now.Add(NativeProofFreshness + time.Nanosecond) }}
|
|
115
|
+
acl := newFixedFDNativeACL(actor, native, boundary)
|
|
116
|
+
acl.now = func() time.Time { return now }
|
|
117
|
+
acl.credentials = func(NativeActor) Code { return "" }
|
|
118
|
+
if code := acl.Authorize(context.Background(), ActionStat, int(file.Fd())); code != ErrStale {
|
|
119
|
+
t.Fatalf("expired proof published: %s", code)
|
|
120
|
+
}
|
|
121
|
+
}
|