@underpostnet/cyberia 3.2.80
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/.dockerignore +14 -0
- package/.env.example +144 -0
- package/.github/workflows/cyberia-client.cd.yml +40 -0
- package/.github/workflows/cyberia-server.cd.yml +40 -0
- package/.github/workflows/docker-image.cyberia-client.ci.yml +71 -0
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +70 -0
- package/.github/workflows/docker-image.cyberia-server.ci.yml +71 -0
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +71 -0
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +53 -0
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +53 -0
- package/.github/workflows/engine-cyberia.cd.yml +157 -0
- package/.github/workflows/engine-cyberia.ci.yml +125 -0
- package/.github/workflows/ghpkg.ci.yml +160 -0
- package/.github/workflows/gitlab.ci.yml +20 -0
- package/.github/workflows/hardhat.ci.yml +82 -0
- package/.github/workflows/npmpkg.ci.yml +126 -0
- package/.github/workflows/publish.ci.yml +87 -0
- package/.github/workflows/publish.cyberia.ci.yml +79 -0
- package/.github/workflows/pwa-microservices-template-page.cd.yml +65 -0
- package/.github/workflows/pwa-microservices-template-test.ci.yml +33 -0
- package/.github/workflows/release.cd.yml +46 -0
- package/.nycrc +9 -0
- package/.prettierignore +12 -0
- package/.prettierrc +9 -0
- package/.vscode/extensions.json +10 -0
- package/.vscode/settings.json +26 -0
- package/CHANGELOG.md +2516 -0
- package/CLI-HELP.md +1099 -0
- package/Dockerfile +161 -0
- package/Dockerfile.dev +161 -0
- package/Dockerfile.test +165 -0
- package/LICENSE +21 -0
- package/README.md +259 -0
- package/baremetal/commission-workflows.json +211 -0
- package/baremetal/packer-workflows.json +24 -0
- package/bin/build.js +261 -0
- package/bin/build.template.js +33 -0
- package/bin/cyberia.js +5627 -0
- package/bin/deploy.js +1547 -0
- package/bin/index.js +5627 -0
- package/bump.config.js +27 -0
- package/compose.env +144 -0
- package/conf.js +952 -0
- package/deployment.yaml +418 -0
- package/docker-compose.yml +434 -0
- package/examples/static-page/README.md +150 -0
- package/examples/static-page/ssr-components/CustomPage.js +554 -0
- package/examples/static-page/static-config-example.json +57 -0
- package/hardhat/.env.example +31 -0
- package/hardhat/contracts/ObjectLayerToken.sol +391 -0
- package/hardhat/deployments/.gitkeep +0 -0
- package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
- package/hardhat/hardhat.config.js +136 -0
- package/hardhat/ignition/modules/.gitkeep +0 -0
- package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
- package/hardhat/networks/besu-object-layer.network.json +138 -0
- package/hardhat/package-lock.json +2871 -0
- package/hardhat/package.json +43 -0
- package/hardhat/scripts/deployObjectLayerToken.js +98 -0
- package/hardhat/test/ObjectLayerToken.js +696 -0
- package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
- package/hardhat/types/ethers-contracts/common.ts +92 -0
- package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
- package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
- package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
- package/hardhat/types/ethers-contracts/index.ts +6 -0
- package/ipfs/configure-ipfs.sh +13 -0
- package/jsconfig.json +9 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +48 -0
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +48 -0
- package/manifests/deployment/adminer/deployment.yaml +32 -0
- package/manifests/deployment/adminer/kustomization.yaml +7 -0
- package/manifests/deployment/adminer/service.yaml +13 -0
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +418 -0
- package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +189 -0
- package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +164 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +163 -0
- package/manifests/deployment/dd-default-development/proxy.yaml +46 -0
- package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
- package/manifests/deployment/fastapi/backend-service.yml +19 -0
- package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
- package/manifests/deployment/fastapi/frontend-service.yml +15 -0
- package/manifests/deployment/fastapi/initial_data.sh +8 -0
- package/manifests/deployment/kafka/deployment.yaml +67 -0
- package/manifests/deployment/mongo-express/deployment.yaml +62 -0
- package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
- package/manifests/deployment/playwright/deployment.yaml +52 -0
- package/manifests/deployment/spark/spark-pi-py.yaml +20 -0
- package/manifests/deployment/tensorflow/tf-gpu-test.yaml +63 -0
- package/manifests/envoy-service-nodeport.yaml +22 -0
- package/manifests/grafana/deployment.yaml +64 -0
- package/manifests/grafana/kustomization.yaml +7 -0
- package/manifests/grafana/pvc.yaml +12 -0
- package/manifests/grafana/service.yaml +14 -0
- package/manifests/grafana/storage-class.yaml +9 -0
- package/manifests/ipfs/configmap.yaml +64 -0
- package/manifests/ipfs/headless-service.yaml +35 -0
- package/manifests/ipfs/kustomization.yaml +8 -0
- package/manifests/ipfs/statefulset.yaml +149 -0
- package/manifests/ipfs/storage-class.yaml +9 -0
- package/manifests/kind-config-dev.yaml +20 -0
- package/manifests/kind-config.yaml +12 -0
- package/manifests/kubeadm-calico-config.yaml +14 -0
- package/manifests/letsencrypt-prod.yaml +14 -0
- package/manifests/lxd/lxd-admin-profile.yaml +26 -0
- package/manifests/lxd/lxd-preseed.yaml +30 -0
- package/manifests/mariadb/kustomization.yaml +9 -0
- package/manifests/mariadb/pv.yaml +12 -0
- package/manifests/mariadb/pvc.yaml +10 -0
- package/manifests/mariadb/service.yaml +10 -0
- package/manifests/mariadb/statefulset.yaml +56 -0
- package/manifests/mariadb/storage-class.yaml +10 -0
- package/manifests/mongodb/headless-service.yaml +10 -0
- package/manifests/mongodb/kustomization.yaml +11 -0
- package/manifests/mongodb/pv-pvc.yaml +59 -0
- package/manifests/mongodb/statefulset.yaml +113 -0
- package/manifests/mongodb/storage-class.yaml +9 -0
- package/manifests/mongodb-4.4/headless-service.yaml +10 -0
- package/manifests/mongodb-4.4/kustomization.yaml +9 -0
- package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
- package/manifests/mongodb-4.4/pv-pvc.yaml +19 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +61 -0
- package/manifests/mongodb-4.4/statefulset.yaml +79 -0
- package/manifests/mongodb-4.4/storage-class.yaml +9 -0
- package/manifests/mysql/kustomization.yaml +7 -0
- package/manifests/mysql/pv-pvc.yaml +27 -0
- package/manifests/mysql/statefulset.yaml +55 -0
- package/manifests/postgresql/configmap.yaml +9 -0
- package/manifests/postgresql/kustomization.yaml +10 -0
- package/manifests/postgresql/pv.yaml +15 -0
- package/manifests/postgresql/pvc.yaml +13 -0
- package/manifests/postgresql/service.yaml +10 -0
- package/manifests/postgresql/statefulset.yaml +37 -0
- package/manifests/prometheus/deployment.yaml +82 -0
- package/manifests/pv-pvc-dd.yaml +34 -0
- package/manifests/valkey/kustomization.yaml +7 -0
- package/manifests/valkey/service.yaml +10 -0
- package/manifests/valkey/statefulset.yaml +37 -0
- package/manifests/valkey/valkey-nodeport.yaml +17 -0
- package/mongodb/entrypoint.sh +76 -0
- package/nginx.conf +128 -0
- package/nodemon.json +6 -0
- package/package.json +101 -0
- package/packer/images/Rocky9Amd64/Makefile +62 -0
- package/packer/images/Rocky9Amd64/QUICKSTART.md +113 -0
- package/packer/images/Rocky9Amd64/README.md +122 -0
- package/packer/images/Rocky9Amd64/http/rocky9.ks.pkrtpl.hcl +114 -0
- package/packer/images/Rocky9Amd64/rocky9.pkr.hcl +164 -0
- package/packer/images/Rocky9Arm64/Makefile +69 -0
- package/packer/images/Rocky9Arm64/README.md +122 -0
- package/packer/images/Rocky9Arm64/http/rocky9.ks.pkrtpl.hcl +114 -0
- package/packer/images/Rocky9Arm64/rocky9.pkr.hcl +171 -0
- package/packer/scripts/fuse-nbd +64 -0
- package/packer/scripts/fuse-tar-root +63 -0
- package/proxy.yaml +189 -0
- package/pv-pvc.yaml +164 -0
- package/scripts/device-scan.sh +65 -0
- package/scripts/disk-clean.sh +182 -0
- package/scripts/disk-devices.sh +13 -0
- package/scripts/gen-fqdns.sh +14 -0
- package/scripts/gpu-diag.sh +19 -0
- package/scripts/ip-info.sh +118 -0
- package/scripts/ipxe-setup.sh +200 -0
- package/scripts/k3s-node-setup.sh +124 -0
- package/scripts/kubeadm-node-setup.sh +317 -0
- package/scripts/link-local-underpost-cli.sh +6 -0
- package/scripts/lxd-vm-setup.sh +208 -0
- package/scripts/maas-nat-firewalld.sh +145 -0
- package/scripts/maas-setup.sh +135 -0
- package/scripts/maas-upload-boot-resource.sh +183 -0
- package/scripts/nat-iptables.sh +111 -0
- package/scripts/nvim.sh +91 -0
- package/scripts/packer-init-vars-file.sh +40 -0
- package/scripts/packer-setup.sh +289 -0
- package/scripts/ports-ls.sh +33 -0
- package/scripts/quick-tftp.sh +19 -0
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/scripts/rocky-kickstart.sh +986 -0
- package/scripts/rocky-pwa.sh +200 -0
- package/scripts/rocky-setup.sh +106 -0
- package/scripts/rpmfusion-ffmpeg-setup.sh +32 -0
- package/scripts/ssl.sh +170 -0
- package/scripts/test-monitor.sh +248 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +30 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +155 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +39 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +382 -0
- package/src/api/core/core.controller.js +8 -0
- package/src/api/core/core.model.js +11 -0
- package/src/api/core/core.router.js +23 -0
- package/src/api/core/core.service.js +30 -0
- package/src/api/crypto/crypto.controller.js +10 -0
- package/src/api/crypto/crypto.model.js +23 -0
- package/src/api/crypto/crypto.router.js +23 -0
- package/src/api/crypto/crypto.service.js +64 -0
- package/src/api/cyberia-action/cyberia-action.controller.js +8 -0
- package/src/api/cyberia-action/cyberia-action.model.js +79 -0
- package/src/api/cyberia-action/cyberia-action.router.js +21 -0
- package/src/api/cyberia-action/cyberia-action.service.js +58 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +27 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +100 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +70 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +8 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +20 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +57 -0
- package/src/api/cyberia-entity/cyberia-entity.controller.js +6 -0
- package/src/api/cyberia-entity/cyberia-entity.model.js +25 -0
- package/src/api/cyberia-entity/cyberia-entity.router.js +17 -0
- package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +6 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +337 -0
- package/src/api/cyberia-instance/cyberia-instance-boot.service.js +57 -0
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +583 -0
- package/src/api/cyberia-instance/cyberia-instance.controller.js +42 -0
- package/src/api/cyberia-instance/cyberia-instance.model.js +117 -0
- package/src/api/cyberia-instance/cyberia-instance.router.js +75 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +190 -0
- package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
- package/src/api/cyberia-instance/cyberia-world-generator.js +618 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +6 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +200 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +17 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
- package/src/api/cyberia-map/cyberia-map.controller.js +6 -0
- package/src/api/cyberia-map/cyberia-map.model.js +33 -0
- package/src/api/cyberia-map/cyberia-map.router.js +19 -0
- package/src/api/cyberia-map/cyberia-map.service.js +76 -0
- package/src/api/cyberia-quest/cyberia-quest.controller.js +9 -0
- package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +26 -0
- package/src/api/cyberia-quest/cyberia-quest.service.js +97 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +6 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +21 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
- package/src/api/cyberia-saga/cyberia-saga.controller.js +6 -0
- package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
- package/src/api/cyberia-saga/cyberia-saga.router.js +17 -0
- package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +1076 -0
- package/src/api/cyberia-skill/cyberia-skill.controller.js +6 -0
- package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
- package/src/api/cyberia-skill/cyberia-skill.router.js +17 -0
- package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
- package/src/api/default/default.controller.js +6 -0
- package/src/api/default/default.model.js +20 -0
- package/src/api/default/default.router.js +21 -0
- package/src/api/default/default.service.js +42 -0
- package/src/api/document/document.controller.js +9 -0
- package/src/api/document/document.model.js +95 -0
- package/src/api/document/document.router.js +32 -0
- package/src/api/document/document.service.js +633 -0
- package/src/api/file/file.controller.js +15 -0
- package/src/api/file/file.model.js +127 -0
- package/src/api/file/file.ref.json +39 -0
- package/src/api/file/file.router.js +36 -0
- package/src/api/file/file.service.js +499 -0
- package/src/api/instance/instance.controller.js +8 -0
- package/src/api/instance/instance.model.js +34 -0
- package/src/api/instance/instance.router.js +27 -0
- package/src/api/instance/instance.service.js +75 -0
- package/src/api/ipfs/ipfs.controller.js +8 -0
- package/src/api/ipfs/ipfs.model.js +77 -0
- package/src/api/ipfs/ipfs.router.js +26 -0
- package/src/api/ipfs/ipfs.service.js +145 -0
- package/src/api/object-layer/object-layer.controller.js +18 -0
- package/src/api/object-layer/object-layer.model.js +200 -0
- package/src/api/object-layer/object-layer.router.js +729 -0
- package/src/api/object-layer/object-layer.service.js +894 -0
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +6 -0
- package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +93 -0
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +17 -0
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +46 -0
- package/src/api/test/test.controller.js +14 -0
- package/src/api/test/test.model.js +14 -0
- package/src/api/test/test.router.js +23 -0
- package/src/api/test/test.service.js +35 -0
- package/src/api/types.js +24 -0
- package/src/api/user/guest.service.js +100 -0
- package/src/api/user/postman_collection.json +216 -0
- package/src/api/user/user.build.js +16 -0
- package/src/api/user/user.controller.js +35 -0
- package/src/api/user/user.model.js +142 -0
- package/src/api/user/user.router.js +367 -0
- package/src/api/user/user.service.js +582 -0
- package/src/api.js +23 -0
- package/src/cli/baremetal.js +3947 -0
- package/src/cli/cloud-init.js +673 -0
- package/src/cli/cluster.js +1395 -0
- package/src/cli/db.js +1533 -0
- package/src/cli/deploy.js +1542 -0
- package/src/cli/docker-compose.js +802 -0
- package/src/cli/env.js +177 -0
- package/src/cli/fs.js +380 -0
- package/src/cli/image.js +389 -0
- package/src/cli/index.js +1059 -0
- package/src/cli/ipfs.js +182 -0
- package/src/cli/kickstart.js +271 -0
- package/src/cli/kubectl.js +214 -0
- package/src/cli/lxd.js +1232 -0
- package/src/cli/monitor.js +659 -0
- package/src/cli/release.js +595 -0
- package/src/cli/repository.js +1969 -0
- package/src/cli/run.js +3326 -0
- package/src/cli/secrets.js +151 -0
- package/src/cli/ssh.js +975 -0
- package/src/cli/static.js +653 -0
- package/src/cli/system.js +332 -0
- package/src/cli/test.js +176 -0
- package/src/client/Cryptokoyn.index.js +30 -0
- package/src/client/CyberiaPortal.index.js +31 -0
- package/src/client/Default.index.js +77 -0
- package/src/client/Itemledger.index.js +35 -0
- package/src/client/Underpost.index.js +31 -0
- package/src/client/components/core/404.js +20 -0
- package/src/client/components/core/500.js +20 -0
- package/src/client/components/core/Account.js +630 -0
- package/src/client/components/core/AgGrid.js +238 -0
- package/src/client/components/core/Alert.js +76 -0
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/Auth.js +353 -0
- package/src/client/components/core/Badge.js +26 -0
- package/src/client/components/core/Blockchain.js +41 -0
- package/src/client/components/core/Blog.js +9 -0
- package/src/client/components/core/BtnIcon.js +109 -0
- package/src/client/components/core/CalendarCore.js +437 -0
- package/src/client/components/core/Chat.js +62 -0
- package/src/client/components/core/ClientEvents.js +163 -0
- package/src/client/components/core/ColorPaletteElement.js +309 -0
- package/src/client/components/core/CommonJs.js +1014 -0
- package/src/client/components/core/Content.js +349 -0
- package/src/client/components/core/Css.js +1134 -0
- package/src/client/components/core/CssCore.js +881 -0
- package/src/client/components/core/D3Chart.js +44 -0
- package/src/client/components/core/Docs.js +478 -0
- package/src/client/components/core/DropDown.js +321 -0
- package/src/client/components/core/EventBus.js +96 -0
- package/src/client/components/core/EventsUI.js +130 -0
- package/src/client/components/core/FileExplorer.js +1406 -0
- package/src/client/components/core/FullScreen.js +201 -0
- package/src/client/components/core/Input.js +537 -0
- package/src/client/components/core/Keyboard.js +80 -0
- package/src/client/components/core/KeyboardAvoidance.js +145 -0
- package/src/client/components/core/LoadingAnimation.js +152 -0
- package/src/client/components/core/LogIn.js +212 -0
- package/src/client/components/core/LogOut.js +72 -0
- package/src/client/components/core/Logger.js +22 -0
- package/src/client/components/core/Modal.js +2956 -0
- package/src/client/components/core/NotificationManager.js +80 -0
- package/src/client/components/core/Pagination.js +252 -0
- package/src/client/components/core/Panel.js +1308 -0
- package/src/client/components/core/PanelForm.js +915 -0
- package/src/client/components/core/Polyhedron.js +947 -0
- package/src/client/components/core/PublicProfile.js +895 -0
- package/src/client/components/core/Recover.js +211 -0
- package/src/client/components/core/Responsive.js +146 -0
- package/src/client/components/core/RichText.js +33 -0
- package/src/client/components/core/Router.js +523 -0
- package/src/client/components/core/Scroll.js +76 -0
- package/src/client/components/core/SearchBox.js +1007 -0
- package/src/client/components/core/SignUp.js +153 -0
- package/src/client/components/core/SocketIo.js +163 -0
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +161 -0
- package/src/client/components/core/ToggleSwitch.js +89 -0
- package/src/client/components/core/ToolTip.js +78 -0
- package/src/client/components/core/Translate.js +694 -0
- package/src/client/components/core/Validator.js +140 -0
- package/src/client/components/core/VanillaJs.js +485 -0
- package/src/client/components/core/Wallet.js +95 -0
- package/src/client/components/core/WebComponent.js +44 -0
- package/src/client/components/core/Webhook.js +58 -0
- package/src/client/components/core/Worker.js +313 -0
- package/src/client/components/core/windowGetDimensions.js +269 -0
- package/src/client/components/cryptokoyn/AppShellCryptokoyn.js +352 -0
- package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
- package/src/client/components/cryptokoyn/CssCryptokoyn.js +212 -0
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +16 -0
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +12 -0
- package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +16 -0
- package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +11 -0
- package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +6 -0
- package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
- package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
- package/src/client/components/cyberia/InstanceEngineCyberia.js +1088 -0
- package/src/client/components/cyberia/InstanceSelectionView.js +900 -0
- package/src/client/components/cyberia/MapEngineCyberia.js +1976 -0
- package/src/client/components/cyberia/ObjectLayerEngine.js +1540 -0
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +2420 -0
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +1522 -0
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +528 -0
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +772 -0
- package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +254 -0
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +21 -0
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +16 -0
- package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +518 -0
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +72 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +16 -0
- package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +13 -0
- package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +6 -0
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +48 -0
- package/src/client/components/default/AppShellDefault.js +765 -0
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/CommonDefault.js +29 -0
- package/src/client/components/default/CssDefault.js +27 -0
- package/src/client/components/default/LogInDefault.js +16 -0
- package/src/client/components/default/LogOutDefault.js +12 -0
- package/src/client/components/default/RouterDefault.js +47 -0
- package/src/client/components/default/SettingsDefault.js +16 -0
- package/src/client/components/default/SignUpDefault.js +11 -0
- package/src/client/components/default/SocketIoDefault.js +6 -0
- package/src/client/components/default/TranslateDefault.js +7 -0
- package/src/client/components/itemledger/AppShellItemledger.js +353 -0
- package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
- package/src/client/components/itemledger/CssItemledger.js +212 -0
- package/src/client/components/itemledger/LogInItemledger.js +17 -0
- package/src/client/components/itemledger/LogOutItemledger.js +12 -0
- package/src/client/components/itemledger/RouterItemledger.js +38 -0
- package/src/client/components/itemledger/SettingsItemledger.js +16 -0
- package/src/client/components/itemledger/SignUpItemledger.js +11 -0
- package/src/client/components/itemledger/SocketIoItemledger.js +6 -0
- package/src/client/components/itemledger/TranslateItemledger.js +7 -0
- package/src/client/components/underpost/AppShellUnderpost.js +691 -0
- package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
- package/src/client/components/underpost/CssUnderpost.js +281 -0
- package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
- package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
- package/src/client/components/underpost/LabGalleryUnderpost.js +79 -0
- package/src/client/components/underpost/LogInUnderpost.js +25 -0
- package/src/client/components/underpost/LogOutUnderpost.js +17 -0
- package/src/client/components/underpost/RouterUnderpost.js +45 -0
- package/src/client/components/underpost/SettingsUnderpost.js +16 -0
- package/src/client/components/underpost/SignUpUnderpost.js +11 -0
- package/src/client/components/underpost/SocketIoUnderpost.js +6 -0
- package/src/client/components/underpost/TranslateUnderpost.js +10 -0
- package/src/client/public/cryptokoyn/assets/banner/koyn-social.png +0 -0
- package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
- package/src/client/public/cryptokoyn/assets/logo/cryptokoyn.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-144x144.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-192x192.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-256x256.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-36x36.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-48x48.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-72x72.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/android-chrome-96x96.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/favicon-16x16.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/favicon-32x32.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/mstile-144x144.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/mstile-150x150.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/mstile-310x150.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/mstile-310x310.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/mstile-70x70.png +0 -0
- package/src/client/public/cryptokoyn/assets/splash/safari-pinned-tab.svg +42 -0
- package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
- package/src/client/public/cryptokoyn/favicon.ico +0 -0
- package/src/client/public/cryptokoyn/microdata.json +85 -0
- package/src/client/public/cryptokoyn/site.webmanifest +57 -0
- package/src/client/public/cryptokoyn/sitemap +148 -0
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +307 -0
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +309 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +204 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +341 -0
- package/src/client/public/cyberia-docs/CYBERIA-LORE.md +84 -0
- package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +294 -0
- package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
- package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +242 -0
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +309 -0
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +228 -0
- package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
- package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +740 -0
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-384x384.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-512x512.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/dark.svg +557 -0
- package/src/client/public/default/assets/background/white.jpg +0 -0
- package/src/client/public/default/assets/background/white0-min.jpg +0 -0
- package/src/client/public/default/assets/background/white0.jpg +0 -0
- package/src/client/public/default/assets/logo/base-icon.png +0 -0
- package/src/client/public/default/assets/logo/underpost.gif +0 -0
- package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
- package/src/client/public/default/browserconfig.xml +12 -0
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon-48x48.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/manifest.webmanifest +69 -0
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/safari-pinned-tab.svg +24 -0
- package/src/client/public/default/site.webmanifest +69 -0
- package/src/client/public/default/sitemap +148 -0
- package/src/client/public/default/yandex-browser-50x50.png +0 -0
- package/src/client/public/default/yandex-browser-manifest.json +9 -0
- package/src/client/public/doc/favicon.ico +0 -0
- package/src/client/public/doc/sitemap +148 -0
- package/src/client/public/itemledger/android-chrome-144x144.png +0 -0
- package/src/client/public/itemledger/android-chrome-192x192.png +0 -0
- package/src/client/public/itemledger/android-chrome-256x256.png +0 -0
- package/src/client/public/itemledger/android-chrome-36x36.png +0 -0
- package/src/client/public/itemledger/android-chrome-384x384.png +0 -0
- package/src/client/public/itemledger/android-chrome-48x48.png +0 -0
- package/src/client/public/itemledger/android-chrome-512x512.png +0 -0
- package/src/client/public/itemledger/android-chrome-72x72.png +0 -0
- package/src/client/public/itemledger/android-chrome-96x96.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-1024x1024.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-167x167.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/itemledger/apple-touch-icon.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1125x2436.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1136x640.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1170x2532.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1179x2556.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1242x2208.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1242x2688.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1284x2778.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1290x2796.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1334x750.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1488x2266.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1536x2048.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1620x2160.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1640x2160.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1668x2224.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1668x2388.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-1792x828.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2048x1536.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2048x2732.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2160x1620.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2160x1640.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2208x1242.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2224x1668.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2266x1488.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2388x1668.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2436x1125.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2532x1170.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2556x1179.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2688x1242.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2732x2048.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2778x1284.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-2796x1290.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-640x1136.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-750x1334.png +0 -0
- package/src/client/public/itemledger/apple-touch-startup-image-828x1792.png +0 -0
- package/src/client/public/itemledger/assets/logo/base-icon.png +0 -0
- package/src/client/public/itemledger/browserconfig.xml +12 -0
- package/src/client/public/itemledger/favicon-16x16.png +0 -0
- package/src/client/public/itemledger/favicon-32x32.png +0 -0
- package/src/client/public/itemledger/favicon-48x48.png +0 -0
- package/src/client/public/itemledger/favicon.ico +0 -0
- package/src/client/public/itemledger/manifest.webmanifest +69 -0
- package/src/client/public/itemledger/microdata.json +71 -0
- package/src/client/public/itemledger/mstile-144x144.png +0 -0
- package/src/client/public/itemledger/mstile-150x150.png +0 -0
- package/src/client/public/itemledger/mstile-310x150.png +0 -0
- package/src/client/public/itemledger/mstile-310x310.png +0 -0
- package/src/client/public/itemledger/mstile-70x70.png +0 -0
- package/src/client/public/itemledger/sitemap +148 -0
- package/src/client/public/itemledger/yandex-browser-50x50.png +0 -0
- package/src/client/public/itemledger/yandex-browser-manifest.json +9 -0
- package/src/client/public/test/favicon.ico +0 -0
- package/src/client/public/test/sitemap +148 -0
- package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +137 -0
- package/src/client/services/core/core.service.js +309 -0
- package/src/client/services/crypto/crypto.service.js +68 -0
- package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
- package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
- package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +137 -0
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
- package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
- package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
- package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
- package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
- package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
- package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
- package/src/client/services/default/default.management.js +1015 -0
- package/src/client/services/default/default.service.js +99 -0
- package/src/client/services/document/document.service.js +134 -0
- package/src/client/services/file/file.service.js +94 -0
- package/src/client/services/instance/instance.management.js +78 -0
- package/src/client/services/instance/instance.service.js +107 -0
- package/src/client/services/ipfs/ipfs.service.js +118 -0
- package/src/client/services/object-layer/object-layer.management.js +414 -0
- package/src/client/services/object-layer/object-layer.service.js +208 -0
- package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +99 -0
- package/src/client/services/test/test.service.js +68 -0
- package/src/client/services/user/guest.service.js +86 -0
- package/src/client/services/user/user.management.js +51 -0
- package/src/client/services/user/user.service.js +106 -0
- package/src/client/ssr/RootDocument.js +237 -0
- package/src/client/ssr/body/404.js +77 -0
- package/src/client/ssr/body/500.js +76 -0
- package/src/client/ssr/body/CacheControl.js +117 -0
- package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +97 -0
- package/src/client/ssr/body/DefaultSplashScreen.js +97 -0
- package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +90 -0
- package/src/client/ssr/head/CryptokoynScripts.js +4 -0
- package/src/client/ssr/head/Css.js +241 -0
- package/src/client/ssr/head/CyberiaPortalScripts.js +6 -0
- package/src/client/ssr/head/DefaultScripts.js +6 -0
- package/src/client/ssr/head/ItemledgerScripts.js +4 -0
- package/src/client/ssr/head/Microdata.js +11 -0
- package/src/client/ssr/head/Production.js +1 -0
- package/src/client/ssr/head/Pwa.js +146 -0
- package/src/client/ssr/head/PwaItemledger.js +197 -0
- package/src/client/ssr/head/Seo.js +15 -0
- package/src/client/ssr/head/UnderpostScripts.js +6 -0
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +20 -0
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +16 -0
- package/src/client/ssr/views/Cyberia404.js +328 -0
- package/src/client/ssr/views/CyberiaServerMetrics.js +1070 -0
- package/src/client/ssr/views/Maintenance.js +64 -0
- package/src/client/ssr/views/NoNetworkConnection.js +68 -0
- package/src/client/ssr/views/Test.js +199 -0
- package/src/client/sw/core.sw.js +274 -0
- package/src/client-builder/client-build-docs.js +493 -0
- package/src/client-builder/client-build-live.js +100 -0
- package/src/client-builder/client-build.js +1092 -0
- package/src/client-builder/client-dev-server.js +88 -0
- package/src/client-builder/client-formatted.js +170 -0
- package/src/client-builder/client-icons.js +108 -0
- package/src/client-builder/ssr.js +124 -0
- package/src/client.build.js +17 -0
- package/src/client.dev.js +21 -0
- package/src/db/DataBaseProvider.js +213 -0
- package/src/db/mariadb/MariaDB.js +72 -0
- package/src/db/mongo/MongoBootstrap.js +657 -0
- package/src/db/mongo/MongooseDB.js +199 -0
- package/src/grpc/cyberia/grpc-server.js +162 -0
- package/src/index.js +357 -0
- package/src/mailer/EmailRender.js +116 -0
- package/src/mailer/MailerProvider.js +213 -0
- package/src/projects/cyberia/atlas-sprite-sheet-generator.js +413 -0
- package/src/projects/cyberia/besu-genesis-generator.js +1630 -0
- package/src/projects/cyberia/catalog-cyberia.js +90 -0
- package/src/projects/cyberia/gemini-client.js +175 -0
- package/src/projects/cyberia/generate-saga.js +2137 -0
- package/src/projects/cyberia/hot-reload-trigger.js +163 -0
- package/src/projects/cyberia/instance-data.js +719 -0
- package/src/projects/cyberia/ipfs-client.js +599 -0
- package/src/projects/cyberia/map-preview-generator.js +304 -0
- package/src/projects/cyberia/object-layer.js +978 -0
- package/src/projects/cyberia/semantic-layer-generator-floor.js +319 -0
- package/src/projects/cyberia/semantic-layer-generator-resource.js +259 -0
- package/src/projects/cyberia/semantic-layer-generator-skin.js +1164 -0
- package/src/projects/cyberia/semantic-layer-generator.js +753 -0
- package/src/projects/cyberia/shape-generator.js +1060 -0
- package/src/projects/underpost/catalog-underpost.js +60 -0
- package/src/proxy.js +19 -0
- package/src/runtime/cyberia-client/Dockerfile +49 -0
- package/src/runtime/cyberia-client/Dockerfile.dev +75 -0
- package/src/runtime/cyberia-server/Dockerfile +43 -0
- package/src/runtime/cyberia-server/Dockerfile.dev +56 -0
- package/src/runtime/engine-cyberia/Dockerfile +161 -0
- package/src/runtime/engine-cyberia/Dockerfile.dev +161 -0
- package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
- package/src/runtime/engine-cyberia/compose.env +144 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +434 -0
- package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
- package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
- package/src/runtime/engine-cyberia/nginx.conf +128 -0
- package/src/runtime/express/Dockerfile +45 -0
- package/src/runtime/express/Express.js +285 -0
- package/src/runtime/lampp/Dockerfile +62 -0
- package/src/runtime/lampp/Lampp.js +359 -0
- package/src/runtime/nginx/Nginx.js +250 -0
- package/src/runtime/wp/Dockerfile +62 -0
- package/src/runtime/wp/Wp.js +642 -0
- package/src/server/auth.js +713 -0
- package/src/server/backup.js +102 -0
- package/src/server/catalog.js +72 -0
- package/src/server/conf.js +2316 -0
- package/src/server/cron.js +476 -0
- package/src/server/crypto.js +210 -0
- package/src/server/data-query.js +461 -0
- package/src/server/dns.js +553 -0
- package/src/server/downloader.js +73 -0
- package/src/server/logger.js +229 -0
- package/src/server/middlewares.js +152 -0
- package/src/server/peer.js +75 -0
- package/src/server/process.js +299 -0
- package/src/server/proxy.js +139 -0
- package/src/server/runtime-status.js +252 -0
- package/src/server/runtime.js +183 -0
- package/src/server/start.js +272 -0
- package/src/server/tls.js +254 -0
- package/src/server/valkey.js +201 -0
- package/src/server.js +25 -0
- package/src/ws/IoInterface.js +129 -0
- package/src/ws/IoServer.js +68 -0
- package/src/ws/core/channels/core.ws.chat.js +68 -0
- package/src/ws/core/channels/core.ws.mailer.js +116 -0
- package/src/ws/core/channels/core.ws.stream.js +90 -0
- package/src/ws/core/core.ws.connection.js +41 -0
- package/src/ws/core/core.ws.emit.js +37 -0
- package/src/ws/core/core.ws.server.js +44 -0
- package/src/ws/default/channels/default.ws.main.js +57 -0
- package/src/ws/default/default.ws.connection.js +35 -0
- package/src/ws/default/default.ws.emit.js +14 -0
- package/src/ws/default/default.ws.server.js +39 -0
- package/test/api.test.js +53 -0
- package/test/crypto.test.js +117 -0
- package/test/cyberia-instance-conf-defaults.test.js +140 -0
- package/test/deploy-monitor.test.js +267 -0
- package/test/shape-generator.test.js +463 -0
- package/tsconfig.docs.json +15 -0
- package/typedoc.dd-cyberia.json +31 -0
- package/typedoc.json +31 -0
package/src/cli/ssh.js
ADDED
|
@@ -0,0 +1,975 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSH module for managing SSH key generation and connection setup.
|
|
3
|
+
* @module src/cli/ssh.js
|
|
4
|
+
* @namespace UnderpostSSH
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { generateRandomPasswordSelection } from '../client/components/core/CommonJs.js';
|
|
8
|
+
import { pbcopy, shellExec } from '../server/process.js';
|
|
9
|
+
import { loggerFactory } from '../server/logger.js';
|
|
10
|
+
import fs from 'fs-extra';
|
|
11
|
+
import Underpost from '../index.js';
|
|
12
|
+
|
|
13
|
+
const logger = loggerFactory(import.meta);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @class UnderpostSSH
|
|
17
|
+
* @description Manages SSH key generation and connection setup.
|
|
18
|
+
* @memberof UnderpostSSH
|
|
19
|
+
*/
|
|
20
|
+
class UnderpostSSH {
|
|
21
|
+
static API = {
|
|
22
|
+
/**
|
|
23
|
+
* Loads configuration node from disk or returns default empty config.
|
|
24
|
+
* @method
|
|
25
|
+
* @function loadConfigNode
|
|
26
|
+
* @memberof UnderpostSSH
|
|
27
|
+
* @param {string} deployId - Deployment ID for the config path
|
|
28
|
+
* @returns {{confNode: Object, confNodePath: string}} Configuration node and its file path
|
|
29
|
+
* @description Loads or creates a config node with users object structure
|
|
30
|
+
*/
|
|
31
|
+
loadConfigNode: (deployId) => {
|
|
32
|
+
const confNodePath = `./engine-private/conf/${deployId}/conf.node.json`;
|
|
33
|
+
const confNode = fs.existsSync(confNodePath) ? JSON.parse(fs.readFileSync(confNodePath, 'utf8')) : { users: {} };
|
|
34
|
+
return { confNode, confNodePath };
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Saves configuration node to disk.
|
|
39
|
+
* @method
|
|
40
|
+
* @function saveConfigNode
|
|
41
|
+
* @memberof UnderpostSSH
|
|
42
|
+
* @param {string} confNodePath - Path to the configuration file
|
|
43
|
+
* @param {Object} confNode - Configuration object to save
|
|
44
|
+
* @returns {void}
|
|
45
|
+
*/
|
|
46
|
+
saveConfigNode: (confNodePath, confNode) => {
|
|
47
|
+
fs.outputFileSync(confNodePath, JSON.stringify(confNode, null, 4), 'utf8');
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Checks if a system user exists.
|
|
52
|
+
* @method
|
|
53
|
+
* @function checkUserExists
|
|
54
|
+
* @memberof UnderpostSSH
|
|
55
|
+
* @param {string} username - Username to check
|
|
56
|
+
* @returns {boolean} True if user exists, false otherwise
|
|
57
|
+
*/
|
|
58
|
+
checkUserExists: (username) => {
|
|
59
|
+
const result = shellExec(`id -u ${username} 2>/dev/null || echo "not_found"`, {
|
|
60
|
+
silent: true,
|
|
61
|
+
stdout: true,
|
|
62
|
+
}).trim();
|
|
63
|
+
return result !== 'not_found';
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gets the home directory for a given user.
|
|
68
|
+
* @method
|
|
69
|
+
* @function getUserHome
|
|
70
|
+
* @memberof UnderpostSSH
|
|
71
|
+
* @param {string} username - Username to get home directory for
|
|
72
|
+
* @returns {string} User's home directory path
|
|
73
|
+
*/
|
|
74
|
+
getUserHome: (username) => {
|
|
75
|
+
return shellExec(`getent passwd ${username} | cut -d: -f6`, {
|
|
76
|
+
silent: true,
|
|
77
|
+
stdout: true,
|
|
78
|
+
}).trim();
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Creates a system user with password and groups.
|
|
83
|
+
* @method
|
|
84
|
+
* @function createSystemUser
|
|
85
|
+
* @memberof UnderpostSSH
|
|
86
|
+
* @param {string} username - Username to create
|
|
87
|
+
* @param {string} password - Password for the user
|
|
88
|
+
* @param {string} groups - Comma-separated list of groups
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
91
|
+
createSystemUser: (username, password, groups) => {
|
|
92
|
+
shellExec(`useradd -m -s /bin/bash ${username}`);
|
|
93
|
+
shellExec(`echo "${username}:${password}" | chpasswd`);
|
|
94
|
+
if (groups) {
|
|
95
|
+
for (const group of groups.split(',').map((g) => g.trim())) {
|
|
96
|
+
shellExec(`usermod -aG "${group}" "${username}"`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Ensures SSH directory exists with proper permissions.
|
|
103
|
+
* @method
|
|
104
|
+
* @function ensureSSHDirectory
|
|
105
|
+
* @memberof UnderpostSSH
|
|
106
|
+
* @param {string} sshDir - Path to SSH directory
|
|
107
|
+
* @returns {void}
|
|
108
|
+
*/
|
|
109
|
+
ensureSSHDirectory: (sshDir) => {
|
|
110
|
+
if (!fs.existsSync(sshDir)) {
|
|
111
|
+
shellExec(`mkdir -p ${sshDir}`);
|
|
112
|
+
shellExec(`chmod 700 ${sshDir}`);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Sets proper permissions on SSH files.
|
|
118
|
+
* @method
|
|
119
|
+
* @function setSSHFilePermissions
|
|
120
|
+
* @memberof UnderpostSSH
|
|
121
|
+
* @param {string} sshDir - SSH directory path
|
|
122
|
+
* @param {string} username - Username for ownership
|
|
123
|
+
* @param {string} [keyPath] - Optional private key path
|
|
124
|
+
* @param {string} [pubKeyPath] - Optional public key path
|
|
125
|
+
* @returns {void}
|
|
126
|
+
*/
|
|
127
|
+
setSSHFilePermissions: (sshDir, username, keyPath, pubKeyPath) => {
|
|
128
|
+
shellExec(`chmod 600 ${sshDir}/authorized_keys`);
|
|
129
|
+
shellExec(`chmod 644 ${sshDir}/known_hosts`);
|
|
130
|
+
if (keyPath) shellExec(`chmod 600 ${keyPath}`);
|
|
131
|
+
if (pubKeyPath) shellExec(`chmod 644 ${pubKeyPath}`);
|
|
132
|
+
shellExec(`chown -R ${username}:${username} ${sshDir}`);
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Configures authorized_keys for a user.
|
|
137
|
+
* @method
|
|
138
|
+
* @function configureAuthorizedKeys
|
|
139
|
+
* @memberof UnderpostSSH
|
|
140
|
+
* @param {string} sshDir - SSH directory path
|
|
141
|
+
* @param {string} pubKeyPath - Public key file path
|
|
142
|
+
* @param {boolean} disablePassword - Whether to add no-forwarding restrictions
|
|
143
|
+
* @returns {void}
|
|
144
|
+
*/
|
|
145
|
+
configureAuthorizedKeys: (sshDir, pubKeyPath, disablePassword) => {
|
|
146
|
+
if (disablePassword) {
|
|
147
|
+
shellExec(`cat >> ${sshDir}/authorized_keys <<EOF
|
|
148
|
+
no-port-forwarding,no-X11-forwarding,no-agent-forwarding ${fs.readFileSync(pubKeyPath, 'utf8')}
|
|
149
|
+
EOF`);
|
|
150
|
+
} else {
|
|
151
|
+
shellExec(`cat ${pubKeyPath} >> ${sshDir}/authorized_keys`);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Configures known_hosts with SSH server keys.
|
|
157
|
+
* @method
|
|
158
|
+
* @function configureKnownHosts
|
|
159
|
+
* @memberof UnderpostSSH
|
|
160
|
+
* @param {string} sshDir - SSH directory path
|
|
161
|
+
* @param {number} port - SSH port number
|
|
162
|
+
* @param {string} [host] - Optional external host to add
|
|
163
|
+
* @returns {void}
|
|
164
|
+
*/
|
|
165
|
+
configureKnownHosts: (sshDir, port, host) => {
|
|
166
|
+
shellExec(`ssh-keyscan -p ${port} -H localhost >> ${sshDir}/known_hosts`);
|
|
167
|
+
shellExec(`ssh-keyscan -p ${port} -H 127.0.0.1 >> ${sshDir}/known_hosts`);
|
|
168
|
+
if (host) shellExec(`ssh-keyscan -p ${port} -H ${host} >> ${sshDir}/known_hosts`);
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Configures sudoers for passwordless sudo or sets user password.
|
|
173
|
+
* @method
|
|
174
|
+
* @function configureSudoAccess
|
|
175
|
+
* @memberof UnderpostSSH
|
|
176
|
+
* @param {string} username - Username to configure
|
|
177
|
+
* @param {string} password - User password
|
|
178
|
+
* @param {boolean} disablePassword - Whether to enable passwordless sudo
|
|
179
|
+
* @returns {void}
|
|
180
|
+
*/
|
|
181
|
+
configureSudoAccess: (username, password, disablePassword) => {
|
|
182
|
+
if (disablePassword) {
|
|
183
|
+
shellExec(`echo '${username} ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/90_${username}`);
|
|
184
|
+
} else {
|
|
185
|
+
shellExec(`echo "${username}:${password}" | sudo chpasswd`);
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Main callback function for SSH operations including user management, key import/export, and SSH service configuration.
|
|
191
|
+
* @async
|
|
192
|
+
* @function callback
|
|
193
|
+
* @memberof UnderpostSSH
|
|
194
|
+
* @param {Object} options - Configuration options for SSH operations
|
|
195
|
+
* @param {string} [options.deployId=''] - Deployment ID context for SSH operations
|
|
196
|
+
* @param {boolean} [options.generate=false] - Generate new SSH credentials
|
|
197
|
+
* @param {string} [options.user=''] - SSH user name (defaults to 'root')
|
|
198
|
+
* @param {string} [options.password=''] - SSH user password (auto-generated if not provided, overridden by saved config if user exists)
|
|
199
|
+
* @param {string} [options.host=''] - SSH host address (defaults to public IP, overridden by saved config if user exists)
|
|
200
|
+
* @param {string} [options.filter=''] - Filter for user/group listings
|
|
201
|
+
* @param {string} [options.groups=''] - Comma-separated list of groups for the user (defaults to 'wheel')
|
|
202
|
+
* @param {number} [options.port=22] - SSH port number
|
|
203
|
+
* @param {boolean} [options.start=false] - Start SSH service with hardened configuration
|
|
204
|
+
* @param {boolean} [options.userAdd=false] - Add a new SSH user and generate keys
|
|
205
|
+
* @param {boolean} [options.userRemove=false] - Remove an SSH user and cleanup keys
|
|
206
|
+
* @param {boolean} [options.userLs=false] - List all SSH users and groups
|
|
207
|
+
* @param {boolean} [options.reset=false] - Reset SSH configuration (clear authorized_keys and known_hosts)
|
|
208
|
+
* @param {boolean} [options.keysList=false] - List authorized SSH keys
|
|
209
|
+
* @param {boolean} [options.hostsList=false] - List known SSH hosts
|
|
210
|
+
* @param {boolean} [options.disablePassword=false] - If true, enable passwordless sudo and add SSH restrictions
|
|
211
|
+
* @param {boolean} [options.keyTest=false] - Test SSH key generation
|
|
212
|
+
* @param {boolean} [options.stop=false] - Stop SSH service
|
|
213
|
+
* @param {boolean} [options.status=false] - Check SSH service status
|
|
214
|
+
* @param {boolean} [options.connectUri=false] - Output SSH connection URI
|
|
215
|
+
* @param {boolean} [options.copy=false] - Copy SSH connection URI to clipboard
|
|
216
|
+
* @returns {Promise<void>}
|
|
217
|
+
* @description
|
|
218
|
+
* Handles various SSH operations:
|
|
219
|
+
* - User creation with automatic key generation and backup
|
|
220
|
+
* - User removal with key cleanup
|
|
221
|
+
* - Key import/export between SSH directory and private backup location
|
|
222
|
+
* - SSH service initialization and hardening
|
|
223
|
+
* - User and group listing with optional filtering
|
|
224
|
+
*/
|
|
225
|
+
callback: async (
|
|
226
|
+
options = {
|
|
227
|
+
deployId: '',
|
|
228
|
+
generate: false,
|
|
229
|
+
user: '',
|
|
230
|
+
password: '',
|
|
231
|
+
host: '',
|
|
232
|
+
filter: '',
|
|
233
|
+
groups: '',
|
|
234
|
+
port: 22,
|
|
235
|
+
start: false,
|
|
236
|
+
userAdd: false,
|
|
237
|
+
userRemove: false,
|
|
238
|
+
userLs: false,
|
|
239
|
+
reset: false,
|
|
240
|
+
keysList: false,
|
|
241
|
+
hostsList: false,
|
|
242
|
+
disablePassword: false,
|
|
243
|
+
keyTest: false,
|
|
244
|
+
stop: false,
|
|
245
|
+
status: false,
|
|
246
|
+
connectUri: false,
|
|
247
|
+
copy: false,
|
|
248
|
+
},
|
|
249
|
+
) => {
|
|
250
|
+
let confNode, confNodePath;
|
|
251
|
+
|
|
252
|
+
// Set defaults
|
|
253
|
+
if (!options.user) options.user = 'root';
|
|
254
|
+
if (!options.host) options.host = await Underpost.dns.getPublicIp();
|
|
255
|
+
if (!options.password) options.password = options.disablePassword ? '' : generateRandomPasswordSelection(16);
|
|
256
|
+
if (!options.groups) options.groups = 'wheel';
|
|
257
|
+
if (!options.port) options.port = 22; // Handle connect uri
|
|
258
|
+
|
|
259
|
+
const userHome = Underpost.ssh.getUserHome(options.user);
|
|
260
|
+
options.userHome = userHome;
|
|
261
|
+
|
|
262
|
+
// Load config and override password and host if user exists in config
|
|
263
|
+
if (options.deployId) {
|
|
264
|
+
const config = Underpost.ssh.loadConfigNode(options.deployId);
|
|
265
|
+
confNode = config.confNode;
|
|
266
|
+
confNodePath = config.confNodePath;
|
|
267
|
+
|
|
268
|
+
if (confNode.users && confNode.users[options.user]) {
|
|
269
|
+
if (confNode.users[options.user].host) {
|
|
270
|
+
options.host = confNode.users[options.user].host;
|
|
271
|
+
logger.info(`Using saved host for user ${options.user}: ${options.host}`);
|
|
272
|
+
}
|
|
273
|
+
if (confNode.users[options.user].password === '') {
|
|
274
|
+
options.disablePassword = true;
|
|
275
|
+
options.password = '';
|
|
276
|
+
logger.info(`Using saved empty password for user ${options.user}`);
|
|
277
|
+
} else if (confNode.users[options.user].password) {
|
|
278
|
+
options.disablePassword = false;
|
|
279
|
+
options.password = confNode.users[options.user].password;
|
|
280
|
+
logger.info(`Using saved password for user ${options.user}`);
|
|
281
|
+
}
|
|
282
|
+
options.port = options.port || confNode.users[options.user].port || 22;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
logger.info('options', options);
|
|
287
|
+
|
|
288
|
+
// Handle connect uri
|
|
289
|
+
if (options.connectUri) {
|
|
290
|
+
const keyPath = `${userHome}/.ssh/id_rsa`;
|
|
291
|
+
const uri = `ssh ${options.user}@${options.host} -i ${keyPath} -p ${options.port}`;
|
|
292
|
+
if (options.copy) {
|
|
293
|
+
pbcopy(uri);
|
|
294
|
+
} else console.log(uri);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Handle reset operation
|
|
299
|
+
if (options.reset) {
|
|
300
|
+
shellExec(`> ${userHome}/.ssh/authorized_keys`);
|
|
301
|
+
shellExec(`> ${userHome}/.ssh/known_hosts`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (options.userLs) {
|
|
305
|
+
const filter = options.filter ? `${options.filter}` : '';
|
|
306
|
+
const groupsOut = shellExec(`getent group${filter ? ` | grep '${filter}'` : ''}`, {
|
|
307
|
+
silent: true,
|
|
308
|
+
stdout: true,
|
|
309
|
+
});
|
|
310
|
+
const usersOut = shellExec(`getent passwd${filter ? ` | grep '${filter}'` : ''}`, {
|
|
311
|
+
silent: true,
|
|
312
|
+
stdout: true,
|
|
313
|
+
});
|
|
314
|
+
console.log('Groups'.bold.blue);
|
|
315
|
+
console.log(`group_name : password_x : GID(Internal Group ID) : user_list`.blue);
|
|
316
|
+
console.log(filter ? groupsOut.replaceAll(filter, filter.red) : groupsOut);
|
|
317
|
+
console.log('Users'.bold.blue);
|
|
318
|
+
console.log(`user : x : UID : GID : GECOS : home_dir : shell`.blue);
|
|
319
|
+
console.log(filter ? usersOut.replaceAll(filter, filter.red) : usersOut);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Handle user removal (works with or without deployId)
|
|
323
|
+
if (options.userRemove) {
|
|
324
|
+
const groups = shellExec(`id -Gn ${options.user}`, { silent: true, stdout: true }).trim().replace(/ /g, ', ');
|
|
325
|
+
shellExec(`userdel -r ${options.user}`);
|
|
326
|
+
|
|
327
|
+
// Remove sudoers file if it exists
|
|
328
|
+
const sudoersFile = `/etc/sudoers.d/90_${options.user}`;
|
|
329
|
+
if (fs.existsSync(sudoersFile)) {
|
|
330
|
+
shellExec(`sudo rm -f ${sudoersFile}`);
|
|
331
|
+
logger.info(`Sudoers file removed: ${sudoersFile}`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Remove the private key copy folder and update config only if deployId is provided
|
|
335
|
+
if (options.deployId) {
|
|
336
|
+
if (!confNode) {
|
|
337
|
+
const config = Underpost.ssh.loadConfigNode(options.deployId);
|
|
338
|
+
confNode = config.confNode;
|
|
339
|
+
confNodePath = config.confNodePath;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const privateCopyDir = `./engine-private/conf/${options.deployId}/users/${options.user}`;
|
|
343
|
+
if (fs.existsSync(privateCopyDir)) {
|
|
344
|
+
fs.removeSync(privateCopyDir);
|
|
345
|
+
logger.info(`Private key copy removed from ${privateCopyDir}`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
delete confNode.users[options.user];
|
|
349
|
+
Underpost.ssh.saveConfigNode(confNodePath, confNode);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
logger.info(`User removed`);
|
|
353
|
+
if (groups) logger.info(`User removed from groups: ${groups}`);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Handle user addition (works with or without deployId)
|
|
358
|
+
if (options.userAdd) {
|
|
359
|
+
let privateCopyDir, privateKeyPath, publicKeyPath, keysExistInBackup, userExistsInConfig;
|
|
360
|
+
|
|
361
|
+
// If deployId is provided, check for existing config and backup keys
|
|
362
|
+
if (options.deployId) {
|
|
363
|
+
if (!confNode) {
|
|
364
|
+
const config = Underpost.ssh.loadConfigNode(options.deployId);
|
|
365
|
+
confNode = config.confNode;
|
|
366
|
+
confNodePath = config.confNodePath;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
userExistsInConfig = confNode.users && confNode.users[options.user];
|
|
370
|
+
privateCopyDir = `./engine-private/conf/${options.deployId}/users/${options.user}`;
|
|
371
|
+
privateKeyPath = `${privateCopyDir}/id_rsa`;
|
|
372
|
+
publicKeyPath = `${privateCopyDir}/id_rsa.pub`;
|
|
373
|
+
keysExistInBackup = fs.existsSync(privateKeyPath) && fs.existsSync(publicKeyPath);
|
|
374
|
+
|
|
375
|
+
// If user exists in config AND keys exist in backup, import those keys
|
|
376
|
+
if (userExistsInConfig && keysExistInBackup) {
|
|
377
|
+
logger.info(`User ${options.user} already exists in config. Importing existing keys...`);
|
|
378
|
+
|
|
379
|
+
// Create system user if it doesn't exist
|
|
380
|
+
const userExists = Underpost.ssh.checkUserExists(options.user);
|
|
381
|
+
if (!userExists) {
|
|
382
|
+
Underpost.ssh.createSystemUser(options.user, options.password, options.groups);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const userHome = Underpost.ssh.getUserHome(options.user);
|
|
386
|
+
const sshDir = `${userHome}/.ssh`;
|
|
387
|
+
Underpost.ssh.ensureSSHDirectory(sshDir);
|
|
388
|
+
|
|
389
|
+
const userKeyPath = `${sshDir}/id_rsa`;
|
|
390
|
+
const userPubKeyPath = `${sshDir}/id_rsa.pub`;
|
|
391
|
+
|
|
392
|
+
// Import keys from backup
|
|
393
|
+
fs.copyFileSync(privateKeyPath, userKeyPath);
|
|
394
|
+
fs.copyFileSync(publicKeyPath, userPubKeyPath);
|
|
395
|
+
|
|
396
|
+
Underpost.ssh.configureAuthorizedKeys(sshDir, userPubKeyPath, options.disablePassword);
|
|
397
|
+
Underpost.ssh.configureSudoAccess(options.user, options.password, options.disablePassword);
|
|
398
|
+
Underpost.ssh.configureKnownHosts(sshDir, options.port, options.host);
|
|
399
|
+
Underpost.ssh.setSSHFilePermissions(sshDir, options.user, userKeyPath, userPubKeyPath);
|
|
400
|
+
|
|
401
|
+
logger.info(`Keys imported from ${privateCopyDir} to ${sshDir}`);
|
|
402
|
+
logger.info(`User added with existing keys`);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// New user or no existing keys - create new user and generate keys
|
|
408
|
+
Underpost.ssh.createSystemUser(options.user, options.password, options.groups);
|
|
409
|
+
|
|
410
|
+
const userHome = Underpost.ssh.getUserHome(options.user);
|
|
411
|
+
const sshDir = `${userHome}/.ssh`;
|
|
412
|
+
Underpost.ssh.ensureSSHDirectory(sshDir);
|
|
413
|
+
|
|
414
|
+
const keyPath = `${sshDir}/id_rsa`;
|
|
415
|
+
const pubKeyPath = `${sshDir}/id_rsa.pub`;
|
|
416
|
+
|
|
417
|
+
if (!fs.existsSync(keyPath)) {
|
|
418
|
+
shellExec(
|
|
419
|
+
`ssh-keygen -t ed25519 -f ${keyPath} -N "${options.password}" -q -C "${options.user}@${options.host}"`,
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
Underpost.ssh.configureAuthorizedKeys(sshDir, pubKeyPath, options.disablePassword);
|
|
424
|
+
Underpost.ssh.configureSudoAccess(options.user, options.password, options.disablePassword);
|
|
425
|
+
Underpost.ssh.configureKnownHosts(sshDir, options.port, options.host);
|
|
426
|
+
Underpost.ssh.setSSHFilePermissions(sshDir, options.user, keyPath, pubKeyPath);
|
|
427
|
+
|
|
428
|
+
// Save a copy of the keys to the private folder only if deployId is provided
|
|
429
|
+
if (options.deployId) {
|
|
430
|
+
if (!privateCopyDir) privateCopyDir = `./engine-private/conf/${options.deployId}/users/${options.user}`;
|
|
431
|
+
fs.ensureDirSync(privateCopyDir);
|
|
432
|
+
|
|
433
|
+
const privateKeyCopyPath = `${privateCopyDir}/id_rsa`;
|
|
434
|
+
const publicKeyCopyPath = `${privateCopyDir}/id_rsa.pub`;
|
|
435
|
+
|
|
436
|
+
fs.copyFileSync(keyPath, privateKeyCopyPath);
|
|
437
|
+
fs.copyFileSync(pubKeyPath, publicKeyCopyPath);
|
|
438
|
+
|
|
439
|
+
logger.info(`Keys backed up to ${privateCopyDir}`);
|
|
440
|
+
|
|
441
|
+
confNode.users[options.user] = {
|
|
442
|
+
...confNode.users[options.user],
|
|
443
|
+
...options,
|
|
444
|
+
keyPath,
|
|
445
|
+
pubKeyPath,
|
|
446
|
+
privateKeyCopyPath,
|
|
447
|
+
publicKeyCopyPath,
|
|
448
|
+
};
|
|
449
|
+
Underpost.ssh.saveConfigNode(confNodePath, confNode);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
logger.info(`User added`);
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Handle config user listing (only with deployId)
|
|
457
|
+
if (options.deployId) {
|
|
458
|
+
if (!confNode) {
|
|
459
|
+
const config = Underpost.ssh.loadConfigNode(options.deployId);
|
|
460
|
+
confNode = config.confNode;
|
|
461
|
+
confNodePath = config.confNodePath;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (options.userLs && confNode && confNode.users) {
|
|
465
|
+
logger.info(`Users in config:`);
|
|
466
|
+
Object.keys(confNode.users).forEach((user) => {
|
|
467
|
+
logger.info(`- ${user}`);
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Handle generate root keys
|
|
473
|
+
if (options.generate)
|
|
474
|
+
Underpost.ssh.generateKeys({ user: options.user, password: options.password, host: options.host });
|
|
475
|
+
|
|
476
|
+
// Handle list operations
|
|
477
|
+
if (options.keysList) shellExec(`cat ${userHome}/.ssh/authorized_keys`);
|
|
478
|
+
if (options.hostsList) shellExec(`cat ${userHome}/.ssh/known_hosts`);
|
|
479
|
+
|
|
480
|
+
// Handle key test
|
|
481
|
+
if (options.keyTest) {
|
|
482
|
+
const keyPath = `${userHome}/.ssh/id_rsa`;
|
|
483
|
+
shellExec(`ssh-keygen -y -f ${keyPath} -P "${options.password}"`);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Handle stop server
|
|
487
|
+
if (options.stop) shellExec('service sshd stop');
|
|
488
|
+
|
|
489
|
+
// Handle start server
|
|
490
|
+
if (options.start) {
|
|
491
|
+
Underpost.ssh.chmod({ user: options.user });
|
|
492
|
+
Underpost.ssh.initService({ port: options.port });
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Handle status server
|
|
496
|
+
if (options.status) shellExec('service sshd status');
|
|
497
|
+
},
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Synchronously copies a local directory to a remote host over key-only SSH,
|
|
501
|
+
* streaming it as a tar archive (no intermediate file) and fixing ownership.
|
|
502
|
+
* Mirrors the kind-node `tar | docker cp` provisioning pattern but targets a
|
|
503
|
+
* real node via SSH, so node-local hostPath volumes can be materialized on the
|
|
504
|
+
* node where the pod will actually run.
|
|
505
|
+
*
|
|
506
|
+
* Idempotent and re-runnable: `mkdir -p` + `tar -x` overwrite in place. Throws
|
|
507
|
+
* on any SSH/tar failure so an empty-volume deploy is never produced silently.
|
|
508
|
+
*
|
|
509
|
+
* @function copyDirToNode
|
|
510
|
+
* @memberof UnderpostSSH
|
|
511
|
+
* @param {object} params
|
|
512
|
+
* @param {string} params.host - Target host/IP (key-only SSH reachable).
|
|
513
|
+
* @param {string} params.localDir - Local source directory.
|
|
514
|
+
* @param {string} params.remoteDir - Destination directory on the node.
|
|
515
|
+
* @param {number} [params.port=22] - SSH port.
|
|
516
|
+
* @param {string} [params.user='root'] - SSH user (key-only).
|
|
517
|
+
* @param {string} [params.keyPath='./engine-private/deploy/id_rsa'] - Private key path.
|
|
518
|
+
* @param {string} [params.owner='1000:1000'] - chown target on the node (empty to skip).
|
|
519
|
+
* @param {string} [params.mode='755'] - chmod mode on the node (empty to skip).
|
|
520
|
+
* @returns {void}
|
|
521
|
+
*/
|
|
522
|
+
copyDirToNode: ({
|
|
523
|
+
host,
|
|
524
|
+
localDir,
|
|
525
|
+
remoteDir,
|
|
526
|
+
port = 22,
|
|
527
|
+
user = 'root',
|
|
528
|
+
keyPath = './engine-private/deploy/id_rsa',
|
|
529
|
+
owner = '1000:1000',
|
|
530
|
+
mode = '755',
|
|
531
|
+
}) => {
|
|
532
|
+
if (!host) throw new Error('copyDirToNode requires a host');
|
|
533
|
+
if (!localDir || !fs.existsSync(localDir)) throw new Error(`copyDirToNode: local dir not found: ${localDir}`);
|
|
534
|
+
if (!remoteDir) throw new Error('copyDirToNode requires a remoteDir');
|
|
535
|
+
try {
|
|
536
|
+
shellExec(`chmod 600 ${keyPath}`, { silent: true, silentOnError: true, disableLog: true });
|
|
537
|
+
const sshOpts = `-i ${keyPath} -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${port}`;
|
|
538
|
+
shellExec(`ssh ${sshOpts} ${user}@${host} 'mkdir -p ${remoteDir}'`, {
|
|
539
|
+
silent: true,
|
|
540
|
+
disableLog: true,
|
|
541
|
+
});
|
|
542
|
+
shellExec(`tar -C ${localDir} -c . | ssh ${sshOpts} ${user}@${host} 'tar -C ${remoteDir} -x'`, {
|
|
543
|
+
silent: true,
|
|
544
|
+
disableLog: true,
|
|
545
|
+
});
|
|
546
|
+
const fixups =
|
|
547
|
+
`${owner ? `chown -R ${owner} ${remoteDir}; ` : ''}${mode ? `chmod -R ${mode} ${remoteDir}` : ''}`.trim();
|
|
548
|
+
if (fixups)
|
|
549
|
+
shellExec(`ssh ${sshOpts} ${user}@${host} '${fixups}'`, {
|
|
550
|
+
silent: true,
|
|
551
|
+
disableLog: true,
|
|
552
|
+
});
|
|
553
|
+
} catch (err) {
|
|
554
|
+
logger.error(`copyDirToNode failed`);
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Generic SSH remote command runner that SSH execution logic.
|
|
561
|
+
* Executes arbitrary shell commands on a remote server via SSH with proper credential handling.
|
|
562
|
+
* @async
|
|
563
|
+
* @function sshRemoteRunner
|
|
564
|
+
* @param {string} remoteCommand - The command to execute on the remote server
|
|
565
|
+
* @param {Object} options - Configuration options for SSH execution
|
|
566
|
+
* @param {string} [options.deployId] - Deployment ID for credential lookup
|
|
567
|
+
* @param {string} [options.user] - SSH user for credential lookup
|
|
568
|
+
* @param {boolean} [options.dev=false] - Development mode flag
|
|
569
|
+
* @param {string} [options.cd='/home/dd/engine'] - Working directory on remote server
|
|
570
|
+
* @param {boolean} [options.useSudo=true] - Whether to use sudo for command execution
|
|
571
|
+
* @param {boolean} [options.remote=true] - Whether to execute as remote command (if false, runs locally)
|
|
572
|
+
* @returns {Promise<string>} Output from the shell execution
|
|
573
|
+
* @memberof UnderpostSSH
|
|
574
|
+
*/
|
|
575
|
+
sshRemoteRunner: async (remoteCommand, options = {}) => {
|
|
576
|
+
const { deployId = '', user = '', dev = false, cd = '/home/dd/engine', useSudo = true, remote = true } = options;
|
|
577
|
+
|
|
578
|
+
// If not executing remotely, just run locally
|
|
579
|
+
if (!remote) {
|
|
580
|
+
return shellExec(remoteCommand);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// Set up SSH credentials from config
|
|
584
|
+
if (deployId && user) {
|
|
585
|
+
await Underpost.ssh.setDefautlSshCredentials({ deployId, user });
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Build the complete SSH command
|
|
589
|
+
const sshScript = `#!/usr/bin/env bash
|
|
590
|
+
set -euo pipefail
|
|
591
|
+
|
|
592
|
+
REMOTE_USER=$(node bin config get --plain DEFAULT_SSH_USER)
|
|
593
|
+
REMOTE_HOST=$(node bin config get --plain DEFAULT_SSH_HOST)
|
|
594
|
+
REMOTE_PORT=$(node bin config get --plain DEFAULT_SSH_PORT)
|
|
595
|
+
SSH_KEY=$(node bin config get --plain DEFAULT_SSH_KEY_PATH)
|
|
596
|
+
|
|
597
|
+
chmod 600 "$SSH_KEY"
|
|
598
|
+
|
|
599
|
+
ssh -i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$REMOTE_USER@$REMOTE_HOST" -p $REMOTE_PORT sh <<EOF
|
|
600
|
+
${cd ? `cd ${cd}` : ''}
|
|
601
|
+
${useSudo ? `sudo -n -- /bin/bash -lc "${remoteCommand}"` : remoteCommand}
|
|
602
|
+
EOF
|
|
603
|
+
`;
|
|
604
|
+
|
|
605
|
+
return shellExec(sshScript, { stdout: true });
|
|
606
|
+
},
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Waits until a TCP SSH port becomes reachable on a host.
|
|
610
|
+
* @async
|
|
611
|
+
* @function waitForSshPort
|
|
612
|
+
* @memberof UnderpostSSH
|
|
613
|
+
* @param {object} params
|
|
614
|
+
* @param {string} params.host - Target host/IP.
|
|
615
|
+
* @param {number} [params.port=22] - SSH port.
|
|
616
|
+
* @param {number} [params.timeoutMs=600000] - Maximum wait window.
|
|
617
|
+
* @param {number} [params.intervalMs=3000] - Poll interval.
|
|
618
|
+
* @returns {Promise<boolean>} True once the port accepts connections, false on timeout.
|
|
619
|
+
*/
|
|
620
|
+
waitForSshPort: async ({ host, port = 22, timeoutMs = 10 * 60 * 1000, intervalMs = 3000 }) => {
|
|
621
|
+
const deadline = Date.now() + timeoutMs;
|
|
622
|
+
while (Date.now() < deadline) {
|
|
623
|
+
const probe = shellExec(
|
|
624
|
+
`timeout 5 bash -c '</dev/tcp/${host}/${port}' >/dev/null 2>&1 && echo open || echo closed`,
|
|
625
|
+
{ silent: true, stdout: true, silentOnError: true, disableLog: true },
|
|
626
|
+
);
|
|
627
|
+
if (`${probe}`.trim() === 'open') return true;
|
|
628
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
629
|
+
}
|
|
630
|
+
logger.warn(`SSH port ${host}:${port} not reachable within timeout`);
|
|
631
|
+
return false;
|
|
632
|
+
},
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Waits until a host's SSH port stops accepting connections (e.g. while it
|
|
636
|
+
* reboots). Used to detect a reboot edge before waiting for the port to come
|
|
637
|
+
* back up, so callers don't latch onto the pre-reboot (ephemeral) sshd.
|
|
638
|
+
* @async
|
|
639
|
+
* @function waitForSshPortClosed
|
|
640
|
+
* @memberof UnderpostSSH
|
|
641
|
+
* @param {object} params
|
|
642
|
+
* @param {string} params.host - Target host/IP.
|
|
643
|
+
* @param {number} [params.port=22] - SSH port.
|
|
644
|
+
* @param {number} [params.timeoutMs=180000] - Maximum wait window.
|
|
645
|
+
* @param {number} [params.intervalMs=3000] - Poll interval.
|
|
646
|
+
* @returns {Promise<boolean>} True once the port is closed, false on timeout.
|
|
647
|
+
*/
|
|
648
|
+
waitForSshPortClosed: async ({ host, port = 22, timeoutMs = 3 * 60 * 1000, intervalMs = 3000 }) => {
|
|
649
|
+
const deadline = Date.now() + timeoutMs;
|
|
650
|
+
while (Date.now() < deadline) {
|
|
651
|
+
const probe = shellExec(
|
|
652
|
+
`timeout 5 bash -c '</dev/tcp/${host}/${port}' >/dev/null 2>&1 && echo open || echo closed`,
|
|
653
|
+
{ silent: true, stdout: true, silentOnError: true, disableLog: true },
|
|
654
|
+
);
|
|
655
|
+
if (`${probe}`.trim() === 'closed') return true;
|
|
656
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
657
|
+
}
|
|
658
|
+
return false;
|
|
659
|
+
},
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Orchestrates a non-interactive, key-only SSH session against a freshly
|
|
663
|
+
* provisioned host: waits for the port, attempts key-based auth, runs a
|
|
664
|
+
* remote command batch, and returns a structured result. Used by the
|
|
665
|
+
* commissioning flow once the ephemeral runtime reports SSH readiness.
|
|
666
|
+
* @async
|
|
667
|
+
* @function sshExecBatch
|
|
668
|
+
* @memberof UnderpostSSH
|
|
669
|
+
* @param {object} params
|
|
670
|
+
* @param {string} params.host - Target host/IP.
|
|
671
|
+
* @param {string} params.command - Remote command batch to execute.
|
|
672
|
+
* @param {number} [params.port=22] - SSH port.
|
|
673
|
+
* @param {string} [params.user='root'] - SSH user (key-only).
|
|
674
|
+
* @param {string} [params.keyPath] - Private key path (defaults to engine deploy key).
|
|
675
|
+
* @param {number} [params.connectTimeoutSec=15] - Per-attempt SSH connect timeout.
|
|
676
|
+
* @param {number} [params.retries=3] - Auth/exec retry attempts.
|
|
677
|
+
* @param {number} [params.retryDelayMs=5000] - Base backoff between retries.
|
|
678
|
+
* @param {number} [params.waitForPortMs=0] - When > 0, wait for the port first.
|
|
679
|
+
* @returns {Promise<{ok: boolean, code: number, stdout: string, stderr: string, attempts: number}>}
|
|
680
|
+
*/
|
|
681
|
+
sshExecBatch: async ({
|
|
682
|
+
host,
|
|
683
|
+
command,
|
|
684
|
+
port = 22,
|
|
685
|
+
user = 'root',
|
|
686
|
+
keyPath = './engine-private/deploy/id_rsa',
|
|
687
|
+
connectTimeoutSec = 15,
|
|
688
|
+
retries = 3,
|
|
689
|
+
retryDelayMs = 5000,
|
|
690
|
+
waitForPortMs = 0,
|
|
691
|
+
}) => {
|
|
692
|
+
if (!host) throw new Error('sshExecBatch requires a host');
|
|
693
|
+
if (!command) throw new Error('sshExecBatch requires a command');
|
|
694
|
+
|
|
695
|
+
if (waitForPortMs > 0) {
|
|
696
|
+
const reachable = await Underpost.ssh.waitForSshPort({ host, port, timeoutMs: waitForPortMs });
|
|
697
|
+
if (!reachable) return { ok: false, code: 255, stdout: '', stderr: 'ssh port unreachable', attempts: 0 };
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
shellExec(`chmod 600 ${keyPath}`, { silent: true, silentOnError: true, disableLog: true });
|
|
701
|
+
|
|
702
|
+
const sshOpts = [
|
|
703
|
+
`-i ${keyPath}`,
|
|
704
|
+
`-o BatchMode=yes`,
|
|
705
|
+
`-o PreferredAuthentications=publickey`,
|
|
706
|
+
`-o PubkeyAuthentication=yes`,
|
|
707
|
+
`-o PasswordAuthentication=no`,
|
|
708
|
+
`-o StrictHostKeyChecking=no`,
|
|
709
|
+
`-o UserKnownHostsFile=/dev/null`,
|
|
710
|
+
`-o ConnectTimeout=${connectTimeoutSec}`,
|
|
711
|
+
// Tolerate a freshly-booted node whose network briefly flaps (e.g. while
|
|
712
|
+
// NetworkManager applies a static profile): retry the TCP connect and
|
|
713
|
+
// keep the session alive across short stalls.
|
|
714
|
+
`-o ConnectionAttempts=3`,
|
|
715
|
+
`-o ServerAliveInterval=10`,
|
|
716
|
+
`-o ServerAliveCountMax=6`,
|
|
717
|
+
`-p ${port}`,
|
|
718
|
+
].join(' ');
|
|
719
|
+
|
|
720
|
+
let last = { ok: false, code: 255, stdout: '', stderr: '', attempts: 0 };
|
|
721
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
722
|
+
const result = shellExec(
|
|
723
|
+
`ssh ${sshOpts} ${user}@${host} bash -s <<'UNDERPOST_SSH_BATCH_EOF'\n${command}\nUNDERPOST_SSH_BATCH_EOF`,
|
|
724
|
+
{
|
|
725
|
+
stdout: false,
|
|
726
|
+
silentOnError: true,
|
|
727
|
+
disableLog: true,
|
|
728
|
+
},
|
|
729
|
+
);
|
|
730
|
+
last = {
|
|
731
|
+
ok: result.code === 0,
|
|
732
|
+
code: result.code,
|
|
733
|
+
stdout: result.stdout || '',
|
|
734
|
+
stderr: result.stderr || '',
|
|
735
|
+
attempts: attempt,
|
|
736
|
+
};
|
|
737
|
+
if (last.ok) {
|
|
738
|
+
logger.info(`sshExecBatch succeeded on ${user}@${host}:${port} (attempt ${attempt})`);
|
|
739
|
+
return last;
|
|
740
|
+
}
|
|
741
|
+
logger.warn(`sshExecBatch attempt ${attempt}/${retries} failed on ${user}@${host}:${port}`, {
|
|
742
|
+
code: last.code,
|
|
743
|
+
stderr: last.stderr.slice(-400),
|
|
744
|
+
});
|
|
745
|
+
if (attempt < retries) await new Promise((r) => setTimeout(r, retryDelayMs * attempt));
|
|
746
|
+
}
|
|
747
|
+
return last;
|
|
748
|
+
},
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Transfers a local script to a remote host and runs it over key-only SSH.
|
|
752
|
+
* The script is base64-encoded so no shell-quoting/escaping is needed, then
|
|
753
|
+
* decoded, made executable, and executed with the given arguments. Reuses
|
|
754
|
+
* sshExecBatch for the actual transport, retries, and structured result.
|
|
755
|
+
* @async
|
|
756
|
+
* @function sshRunScript
|
|
757
|
+
* @memberof UnderpostSSH
|
|
758
|
+
* @param {object} params
|
|
759
|
+
* @param {string} params.host - Target host/IP.
|
|
760
|
+
* @param {string} params.scriptPath - Local path to the script to run.
|
|
761
|
+
* @param {string} [params.args=''] - Arguments appended to the remote invocation.
|
|
762
|
+
* @param {object} [params.env={}] - Environment variables exported for the remote run (e.g. secrets). Passed inline to the command, never echoed.
|
|
763
|
+
* @param {string} [params.remotePath='/tmp/underpost-remote-script.sh'] - Remote path to write the script.
|
|
764
|
+
* @param {number} [params.port=22] - SSH port.
|
|
765
|
+
* @param {string} [params.user='root'] - SSH user (key-only).
|
|
766
|
+
* @param {string} [params.keyPath] - Private key path (defaults to engine deploy key).
|
|
767
|
+
* @param {number} [params.retries=3] - Retry attempts.
|
|
768
|
+
* @param {number} [params.waitForPortMs=0] - When > 0, wait for the port first.
|
|
769
|
+
* @returns {Promise<{ok: boolean, code: number, stdout: string, stderr: string, attempts: number}>}
|
|
770
|
+
*/
|
|
771
|
+
sshRunScript: async ({
|
|
772
|
+
host,
|
|
773
|
+
scriptPath,
|
|
774
|
+
args = '',
|
|
775
|
+
env = {},
|
|
776
|
+
remotePath = '/tmp/underpost-remote-script.sh',
|
|
777
|
+
port = 22,
|
|
778
|
+
user = 'root',
|
|
779
|
+
keyPath = './engine-private/deploy/id_rsa',
|
|
780
|
+
retries = 3,
|
|
781
|
+
waitForPortMs = 0,
|
|
782
|
+
}) => {
|
|
783
|
+
if (!fs.existsSync(scriptPath)) throw new Error(`sshRunScript: script not found: ${scriptPath}`);
|
|
784
|
+
const b64 = Buffer.from(fs.readFileSync(scriptPath, 'utf8'), 'utf8').toString('base64');
|
|
785
|
+
// Inline env assignments (single-quote escaped) so secrets are exported for
|
|
786
|
+
// the remote run without appearing as logged CLI args.
|
|
787
|
+
const sq = (v) => `'${String(v).replace(/'/g, "'\\''")}'`;
|
|
788
|
+
const envPrefix = Object.entries(env)
|
|
789
|
+
.filter(([, v]) => v !== undefined && v !== null && `${v}` !== '')
|
|
790
|
+
.map(([k, v]) => `${k}=${sq(v)}`)
|
|
791
|
+
.join(' ');
|
|
792
|
+
const command = [
|
|
793
|
+
'set -e',
|
|
794
|
+
`echo '${b64}' | base64 -d > ${remotePath}`,
|
|
795
|
+
`chmod +x ${remotePath}`,
|
|
796
|
+
`${envPrefix ? `${envPrefix} ` : ''}bash ${remotePath} ${args}`,
|
|
797
|
+
].join('\n');
|
|
798
|
+
return Underpost.ssh.sshExecBatch({ host, port, user, keyPath, retries, waitForPortMs, command });
|
|
799
|
+
},
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Loads saved SSH credentials from config and sets them in the UnderpostRootEnv API.
|
|
803
|
+
* @async
|
|
804
|
+
* @function setDefautlSshCredentials
|
|
805
|
+
* @memberof UnderpostSSH
|
|
806
|
+
* @param {Object} options - Options for setting default SSH credentials
|
|
807
|
+
* @param {string} options.deployId - Deployment ID for the config path
|
|
808
|
+
* @param {string} options.user - SSH user name
|
|
809
|
+
* @returns {Promise<void>}
|
|
810
|
+
*/
|
|
811
|
+
setDefautlSshCredentials: async (options = { deployId: '', user: '' }) => {
|
|
812
|
+
const confNodePath = `./engine-private/conf/${options.deployId}/conf.node.json`;
|
|
813
|
+
if (fs.existsSync(confNodePath)) {
|
|
814
|
+
const { users } = JSON.parse(fs.readFileSync(confNodePath, 'utf8'));
|
|
815
|
+
const { user, host, keyPath, port } = users[options.user];
|
|
816
|
+
Underpost.env.set('DEFAULT_SSH_USER', user);
|
|
817
|
+
Underpost.env.set('DEFAULT_SSH_HOST', host);
|
|
818
|
+
Underpost.env.set('DEFAULT_SSH_KEY_PATH', keyPath);
|
|
819
|
+
Underpost.env.set('DEFAULT_SSH_PORT', port);
|
|
820
|
+
} else logger.warn(`No SSH config found at ${confNodePath}`);
|
|
821
|
+
},
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Generates new SSH ED25519 key pair and stores copies in multiple locations.
|
|
825
|
+
* @function generateKeys
|
|
826
|
+
* @memberof UnderpostSSH
|
|
827
|
+
* @param {Object} params - Key generation parameters
|
|
828
|
+
* @param {string} params.user - Username for the SSH key comment
|
|
829
|
+
* @param {string} params.password - Password to encrypt the private key
|
|
830
|
+
* @param {string} params.host - Host address for the SSH key comment
|
|
831
|
+
* @returns {void}
|
|
832
|
+
* @description
|
|
833
|
+
* Creates a new SSH ED25519 key pair and distributes it to:
|
|
834
|
+
* - User's ~/.ssh/ directory
|
|
835
|
+
* - ./engine-private/deploy/ directory
|
|
836
|
+
* Cleans up temporary key files after copying.
|
|
837
|
+
*/
|
|
838
|
+
generateKeys: ({ user, password, host }) => {
|
|
839
|
+
shellExec(`sudo rm -rf ./id_rsa`);
|
|
840
|
+
shellExec(`sudo rm -rf ./id_rsa.pub`);
|
|
841
|
+
|
|
842
|
+
shellExec(`ssh-keygen -t ed25519 -f id_rsa -N "${password}" -q -C "${user}@${host}"`);
|
|
843
|
+
|
|
844
|
+
shellExec(`sudo cp ./id_rsa ~/.ssh/id_rsa`);
|
|
845
|
+
shellExec(`sudo cp ./id_rsa.pub ~/.ssh/id_rsa.pub`);
|
|
846
|
+
|
|
847
|
+
shellExec(`sudo cp ./id_rsa ./engine-private/deploy/id_rsa`);
|
|
848
|
+
shellExec(`sudo cp ./id_rsa.pub ./engine-private/deploy/id_rsa.pub`);
|
|
849
|
+
|
|
850
|
+
shellExec(`sudo rm -rf ./id_rsa`);
|
|
851
|
+
shellExec(`sudo rm -rf ./id_rsa.pub`);
|
|
852
|
+
},
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Sets proper permissions and ownership for SSH directories and files.
|
|
856
|
+
* @function chmod
|
|
857
|
+
* @memberof UnderpostSSH
|
|
858
|
+
* @param {Object} params - Permission configuration parameters
|
|
859
|
+
* @param {string} params.user - Username for setting ownership
|
|
860
|
+
* @returns {void}
|
|
861
|
+
* @description
|
|
862
|
+
* Applies secure permissions to SSH files:
|
|
863
|
+
* - ~/.ssh/ directory: 700
|
|
864
|
+
* - ~/.ssh/authorized_keys: 600
|
|
865
|
+
* - ~/.ssh/known_hosts: 644
|
|
866
|
+
* - ~/.ssh/id_rsa: 600
|
|
867
|
+
* - /etc/ssh/ssh_host_ed25519_key: 600
|
|
868
|
+
* Sets ownership to specified user for ~/.ssh/ and contents.
|
|
869
|
+
*/
|
|
870
|
+
chmod: ({ user }) => {
|
|
871
|
+
shellExec(`sudo chmod 700 ~/.ssh/`);
|
|
872
|
+
shellExec(`sudo chmod 600 ~/.ssh/authorized_keys`);
|
|
873
|
+
shellExec(`sudo chmod 644 ~/.ssh/known_hosts`);
|
|
874
|
+
shellExec(`sudo chmod 600 ~/.ssh/id_rsa`);
|
|
875
|
+
shellExec(`sudo chmod 600 /etc/ssh/ssh_host_ed25519_key`);
|
|
876
|
+
shellExec(`chown -R ${user}:${user} ~/.ssh`);
|
|
877
|
+
},
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Initializes and hardens SSH service configuration for RHEL-based systems.
|
|
881
|
+
* @function initService
|
|
882
|
+
* @memberof UnderpostSSH
|
|
883
|
+
* @param {Object} params - Service configuration parameters
|
|
884
|
+
* @param {number} params.port - Port number for SSH service
|
|
885
|
+
* @returns {void}
|
|
886
|
+
* @description
|
|
887
|
+
* Configures SSH daemon with hardened security settings:
|
|
888
|
+
* - Disables password authentication (key-only)
|
|
889
|
+
* - Disables root login
|
|
890
|
+
* - Enables ED25519 host key
|
|
891
|
+
* - Disables X11 forwarding and TCP forwarding
|
|
892
|
+
* - Sets client alive intervals to prevent ghost connections
|
|
893
|
+
* - Configures PAM for RHEL/SELinux compatibility
|
|
894
|
+
*
|
|
895
|
+
* After configuration:
|
|
896
|
+
* - Enables sshd service for auto-start on boot
|
|
897
|
+
* - Restarts sshd service to apply changes
|
|
898
|
+
* - Displays service status with colored output
|
|
899
|
+
*/
|
|
900
|
+
initService: ({ port }) => {
|
|
901
|
+
shellExec(
|
|
902
|
+
`sudo tee /etc/ssh/sshd_config <<EOF
|
|
903
|
+
# ==============================================================
|
|
904
|
+
# RHEL Hardened SSHD Configuration
|
|
905
|
+
# ==============================================================
|
|
906
|
+
|
|
907
|
+
# --- Network Settings ---
|
|
908
|
+
Port ${port ? port : '22'}
|
|
909
|
+
# Explicitly listen on all interfaces (IPv4 and IPv6)
|
|
910
|
+
|
|
911
|
+
# --- Host Keys ---
|
|
912
|
+
# ED25519 is the modern standard (Fast & Secure)
|
|
913
|
+
HostKey /etc/ssh/ssh_host_ed25519_key
|
|
914
|
+
# RSA is kept for compatibility with older clients (Optional)
|
|
915
|
+
# HostKey /etc/ssh/ssh_host_rsa_key
|
|
916
|
+
|
|
917
|
+
# --- Logging ---
|
|
918
|
+
SyslogFacility AUTHPRIV
|
|
919
|
+
# VERBOSE logs the key fingerprint used for login (Audit trail)
|
|
920
|
+
LogLevel VERBOSE
|
|
921
|
+
|
|
922
|
+
# --- Authentication & Security ---
|
|
923
|
+
# STRICTLY KEY-BASED AUTHENTICATION
|
|
924
|
+
PubkeyAuthentication yes
|
|
925
|
+
PasswordAuthentication no
|
|
926
|
+
ChallengeResponseAuthentication no
|
|
927
|
+
PermitEmptyPasswords no
|
|
928
|
+
|
|
929
|
+
# PREVENT ROOT LOGIN
|
|
930
|
+
# Administrators should log in as a standard user and use 'sudo'
|
|
931
|
+
PermitRootLogin no
|
|
932
|
+
|
|
933
|
+
# Security checks on ownership of ~/.ssh/ files
|
|
934
|
+
StrictModes yes
|
|
935
|
+
MaxAuthTries 3
|
|
936
|
+
LoginGraceTime 60
|
|
937
|
+
|
|
938
|
+
# --- PAM (Pluggable Authentication Modules) ---
|
|
939
|
+
# REQUIRED: Must be 'yes' on RHEL for proper session/SELinux handling.
|
|
940
|
+
# Since PasswordAuthentication is 'no', PAM will not ask for passwords.
|
|
941
|
+
UsePAM yes
|
|
942
|
+
|
|
943
|
+
# --- Session & Network Health ---
|
|
944
|
+
# Disconnect idle sessions after 5 minutes (300s * 0) to prevent ghost connections
|
|
945
|
+
ClientAliveInterval 300
|
|
946
|
+
ClientAliveCountMax 0
|
|
947
|
+
|
|
948
|
+
# --- Feature Restrictions ---
|
|
949
|
+
# Disable GUI forwarding unless explicitly needed
|
|
950
|
+
X11Forwarding no
|
|
951
|
+
# Disable DNS checks for faster logins (unless you use Host based auth)
|
|
952
|
+
UseDNS no
|
|
953
|
+
# Disable tunneling unless needed
|
|
954
|
+
PermitTunnel no
|
|
955
|
+
AllowTcpForwarding no
|
|
956
|
+
|
|
957
|
+
# --- Subsystem ---
|
|
958
|
+
Subsystem sftp /usr/libexec/openssh/sftp-server
|
|
959
|
+
EOF`,
|
|
960
|
+
{ disableLog: true },
|
|
961
|
+
);
|
|
962
|
+
shellExec(`sudo systemctl enable sshd`);
|
|
963
|
+
shellExec(`sudo systemctl restart sshd`);
|
|
964
|
+
|
|
965
|
+
const status = shellExec(`sudo systemctl status sshd`, { silent: true, stdout: true });
|
|
966
|
+
if (status.match('running')) console.log(status.replaceAll(`running`, `running`.green));
|
|
967
|
+
else {
|
|
968
|
+
logger.error('SSHD service failed to start');
|
|
969
|
+
console.log(status);
|
|
970
|
+
}
|
|
971
|
+
},
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
export default UnderpostSSH;
|