├── provider ├── blank ├── .gitignore ├── pkg │ ├── pconst │ │ └── pconst.go │ ├── util │ │ ├── func.go │ │ ├── structure │ │ │ └── structure.go │ │ ├── trace │ │ │ └── trace.go │ │ ├── uuid │ │ │ └── uuid.go │ │ └── json │ │ │ └── json.go │ ├── errors │ │ └── errors.go │ ├── web3 │ │ └── eth │ │ │ └── eth.go │ ├── logger │ │ └── hook │ │ │ └── redis │ │ │ └── redis.go │ └── certificate │ │ └── verify.go ├── Dockerfile ├── internal │ ├── bll │ │ └── bll.go │ ├── schema │ │ ├── schema.go │ │ └── s_resource.go │ ├── contextx │ │ └── contextx.go │ ├── dao │ │ └── provider │ │ │ ├── service │ │ │ └── provider.go │ │ │ └── model │ │ │ └── provider.go │ ├── server │ │ ├── eth.go │ │ └── node.go │ └── logger.go ├── cmd │ └── main.go ├── Makefile ├── README.md └── configs │ └── config.toml ├── portal ├── .env.production ├── .browserslistrc ├── src │ ├── styles │ │ ├── index.scss │ │ └── variables.scss │ ├── utils │ │ ├── event-bus.js │ │ ├── cache.js │ │ ├── request.js │ │ └── request-helper.js │ ├── assets │ │ ├── bg.png │ │ ├── logo.png │ │ ├── logo2.png │ │ └── logo.svg │ ├── api │ │ ├── user.js │ │ ├── index.js │ │ ├── nodes.js │ │ ├── servers.js │ │ ├── relay.js │ │ ├── resource.js │ │ └── clients.js │ ├── plugins │ │ └── vuetify.js │ ├── permission.js │ ├── main.js │ ├── store │ │ └── index.js │ ├── router │ │ └── index.js │ ├── App.vue │ ├── views │ │ ├── login.vue │ │ └── HomeView.vue │ └── components │ │ └── pem-dialog.vue ├── .env.test ├── cypress.json ├── jest.config.js ├── .env.development ├── public │ ├── favicon.ico │ ├── favicon.png │ └── index.html ├── babel.config.js ├── Dockerfile ├── tests │ ├── e2e │ │ ├── .eslintrc.js │ │ ├── specs │ │ │ └── test.js │ │ ├── support │ │ │ ├── index.js │ │ │ └── commands.js │ │ └── plugins │ │ │ └── index.js │ └── unit │ │ └── example.spec.js ├── jsconfig.json ├── vue.config.js ├── .gitignore ├── docs │ └── docker.md ├── README.md └── package.json ├── fullnode ├── app │ ├── v1 │ │ ├── user │ │ │ ├── dao │ │ │ │ └── api │ │ │ │ │ ├── facebook.go │ │ │ │ │ ├── google.go │ │ │ │ │ └── github.go │ │ │ ├── model │ │ │ │ ├── mparam │ │ │ │ │ └── user.go │ │ │ │ ├── mmysql │ │ │ │ │ └── user.go │ │ │ │ └── mapi │ │ │ │ │ └── github.go │ │ │ └── controller │ │ │ │ └── user.go │ │ ├── controlplane │ │ │ ├── model │ │ │ │ └── mparam │ │ │ │ │ └── machine.go │ │ │ └── controller │ │ │ │ └── machine.go │ │ ├── node │ │ │ └── model │ │ │ │ ├── mapi │ │ │ │ └── node.go │ │ │ │ ├── mparam │ │ │ │ └── node.go │ │ │ │ └── mmysql │ │ │ │ └── node.go │ │ └── access │ │ │ └── model │ │ │ ├── mapi │ │ │ ├── resource.go │ │ │ └── client.go │ │ │ ├── mmysql │ │ │ ├── resource.go │ │ │ └── client.go │ │ │ └── mparam │ │ │ ├── resource.go │ │ │ └── client.go │ └── base │ │ ├── mapi │ │ └── base.go │ │ ├── controller │ │ ├── home.go │ │ └── controller.go │ │ └── mdb │ │ └── paginate.go ├── work.jpg ├── .gitignore ├── examples │ └── helm │ │ ├── Chart.yaml │ │ ├── templates │ │ ├── service.yaml │ │ ├── ingress.yaml │ │ └── deployment-portal.yaml │ │ └── values.yaml ├── test │ ├── base64_test.go │ ├── key_test.go │ └── json_test.go ├── pkg │ ├── curl │ │ └── curl.go │ ├── logger │ │ └── config.go │ ├── middle │ │ ├── cors.go │ │ ├── session.go │ │ └── oauth2.go │ ├── redis │ │ └── redis.go │ ├── oauth2 │ │ └── option.go │ ├── util │ │ └── json │ │ │ └── json.go │ ├── schema │ │ └── s_server.go │ ├── p2p │ │ └── server.go │ └── confer │ │ ├── config_app.go │ │ └── viper.go ├── Dockerfile ├── route │ ├── node │ │ └── node.go │ ├── controlplane │ │ └── controlplane.go │ ├── user │ │ └── user.go │ ├── route.go │ └── access │ │ └── access.go ├── server │ ├── http.go │ └── init.go ├── main.go ├── config.yaml ├── config_nervos.yaml ├── config_eth.yaml ├── agent │ ├── user.go │ └── client.go ├── pconst │ ├── api.go │ └── code.go ├── Makefile └── config_dev.yaml ├── deploy ├── provider │ ├── db │ │ └── sqlite.db │ ├── sqlite_config.yaml │ └── docker-compose.yaml └── fullnode │ └── docker-compose │ ├── db │ └── sqlite.db │ ├── ca_config.json │ └── nginx.conf ├── client ├── .gitignore ├── configs │ ├── embed.go │ └── config.toml ├── pkg │ ├── pconst │ │ └── pconst.go │ ├── util │ │ ├── structure │ │ │ └── structure.go │ │ ├── trace │ │ │ └── trace.go │ │ ├── func.go │ │ ├── uuid │ │ │ └── uuid.go │ │ └── json │ │ │ └── json.go │ ├── errors │ │ └── errors.go │ ├── logger │ │ └── hook │ │ │ └── redis │ │ │ └── redis.go │ └── certificate │ │ └── verify.go ├── internal │ ├── bll │ │ └── bll.go │ ├── machine.go │ ├── contextx │ │ └── contextx.go │ ├── schema │ │ ├── schema.go │ │ ├── s_server.go │ │ └── s_resource.go │ └── logger.go ├── go.mod ├── cmd │ └── main.go └── README.md ├── verifier ├── app │ ├── v1 │ │ └── node │ │ │ ├── model │ │ │ └── mparam │ │ │ │ └── health.go │ │ │ ├── service │ │ │ └── health.go │ │ │ └── controller │ │ │ └── health.go │ └── base │ │ ├── mapi │ │ └── base.go │ │ ├── controller │ │ ├── home.go │ │ └── controller.go │ │ └── mdb │ │ └── paginate.go ├── verify │ ├── options.go │ ├── record.go │ └── provider.go ├── route │ ├── health │ │ └── health.go │ └── route.go ├── pkg │ ├── logger │ │ └── config.go │ ├── middle │ │ └── cors.go │ ├── confer │ │ ├── config_code.go │ │ └── config_app.go │ ├── gin │ │ └── gin.go │ └── mysql │ │ └── mysql.go ├── Dockerfile ├── config.yaml ├── config_dev.yaml ├── server │ ├── http.go │ └── init.go ├── main.go └── pconst │ ├── api.go │ └── code.go ├── contract ├── artifacts │ ├── contracts │ │ └── CloudSlitDao.sol │ │ │ └── CloudSlitDao.dbg.json │ └── @openzeppelin │ │ ├── contracts │ │ ├── utils │ │ │ └── Context.sol │ │ │ │ ├── Context.dbg.json │ │ │ │ └── Context.json │ │ └── token │ │ │ └── ERC20 │ │ │ ├── ERC20.sol │ │ │ └── ERC20.dbg.json │ │ │ ├── IERC20.sol │ │ │ └── IERC20.dbg.json │ │ │ └── extensions │ │ │ └── IERC20Metadata.sol │ │ │ └── IERC20Metadata.dbg.json │ │ └── contracts-upgradeable │ │ ├── proxy │ │ └── utils │ │ │ └── Initializable.sol │ │ │ ├── Initializable.dbg.json │ │ │ └── Initializable.json │ │ ├── utils │ │ ├── AddressUpgradeable.sol │ │ │ ├── AddressUpgradeable.dbg.json │ │ │ └── AddressUpgradeable.json │ │ └── ContextUpgradeable.sol │ │ │ ├── ContextUpgradeable.dbg.json │ │ │ └── ContextUpgradeable.json │ │ ├── access │ │ └── OwnableUpgradeable.sol │ │ │ ├── OwnableUpgradeable.dbg.json │ │ │ └── OwnableUpgradeable.json │ │ ├── security │ │ └── PausableUpgradeable.sol │ │ │ ├── PausableUpgradeable.dbg.json │ │ │ └── PausableUpgradeable.json │ │ └── token │ │ └── ERC20 │ │ ├── ERC20Upgradeable.sol │ │ └── ERC20Upgradeable.dbg.json │ │ ├── IERC20Upgradeable.sol │ │ └── IERC20Upgradeable.dbg.json │ │ └── extensions │ │ ├── ERC20BurnableUpgradeable.sol │ │ └── ERC20BurnableUpgradeable.dbg.json │ │ └── IERC20MetadataUpgradeable.sol │ │ └── IERC20MetadataUpgradeable.dbg.json ├── .gitignore ├── scripts │ ├── upgrade.js │ └── deploy.js ├── package.json └── hardhat.config.js ├── ca ├── conf.yml ├── util │ ├── cert.go │ ├── ip_addr.go │ └── cache.go ├── ca │ └── singleca │ │ └── err.go ├── .gitignore ├── Dockerfile ├── pkg │ ├── spiffe │ │ ├── idg_test.go │ │ └── idg.go │ ├── logger │ │ ├── redis_hook │ │ │ ├── loggers.go │ │ │ └── redis_hook.go │ │ ├── logger_test.go │ │ └── example │ │ │ └── single_test.go │ ├── signature │ │ ├── signer_test.go │ │ ├── signer.go │ │ └── util.go │ ├── keyprovider │ │ └── xkey_provider_test.go │ └── pkiutil │ │ └── dual_use.go ├── core │ ├── state.go │ └── config │ │ └── types.go ├── Makefile ├── initer │ ├── initer.go │ └── logger.go ├── main.go └── config.json ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ └── build.yml └── LICENSE /provider/blank: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /portal/.env.production: -------------------------------------------------------------------------------- 1 | VUE_APP_BASE_URL="/api/v1" 2 | -------------------------------------------------------------------------------- /fullnode/app/v1/user/dao/api/facebook.go: -------------------------------------------------------------------------------- 1 | package api 2 | -------------------------------------------------------------------------------- /fullnode/app/v1/user/dao/api/google.go: -------------------------------------------------------------------------------- 1 | package api 2 | -------------------------------------------------------------------------------- /portal/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /portal/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | .cur-p { 2 | cursor: pointer; 3 | } 4 | -------------------------------------------------------------------------------- /portal/.env.test: -------------------------------------------------------------------------------- 1 | VUE_APP_BASE_URL="https://www.cloudslit.xyz/test/api" 2 | -------------------------------------------------------------------------------- /portal/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /fullnode/work.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/fullnode/work.jpg -------------------------------------------------------------------------------- /portal/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest' 3 | } 4 | -------------------------------------------------------------------------------- /portal/src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | // 用于覆盖原有的 variable 2 | //$btn-text-transform: unset; 3 | -------------------------------------------------------------------------------- /portal/.env.development: -------------------------------------------------------------------------------- 1 | # use mock api 2 | VUE_APP_BASE_URL="https://dev.cloudslit.xyz/api/v1" 3 | -------------------------------------------------------------------------------- /portal/src/utils/event-bus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export const EventBus = new Vue() 4 | -------------------------------------------------------------------------------- /portal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/portal/public/favicon.ico -------------------------------------------------------------------------------- /portal/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/portal/public/favicon.png -------------------------------------------------------------------------------- /portal/src/assets/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/portal/src/assets/bg.png -------------------------------------------------------------------------------- /provider/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | cert 3 | .vscode 4 | bin 5 | .DS_store 6 | .history 7 | vendor 8 | machine.lock -------------------------------------------------------------------------------- /deploy/provider/db/sqlite.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/deploy/provider/db/sqlite.db -------------------------------------------------------------------------------- /portal/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/portal/src/assets/logo.png -------------------------------------------------------------------------------- /portal/src/assets/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/portal/src/assets/logo2.png -------------------------------------------------------------------------------- /portal/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | cert 3 | .vscode 4 | bin 5 | .DS_store 6 | .history 7 | vendor 8 | machine.lock 9 | config.toml -------------------------------------------------------------------------------- /client/configs/embed.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import _ "embed" 4 | 5 | //go:embed config.toml 6 | var ConfigFileData []byte 7 | -------------------------------------------------------------------------------- /deploy/fullnode/docker-compose/db/sqlite.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlowShield/flowshield/HEAD/deploy/fullnode/docker-compose/db/sqlite.db -------------------------------------------------------------------------------- /client/pkg/pconst/pconst.go: -------------------------------------------------------------------------------- 1 | package pconst 2 | 3 | const ( 4 | OperatorClient = "Client" 5 | OperatorRelay = "Relay" 6 | OperatorServer = "Server" 7 | ) 8 | -------------------------------------------------------------------------------- /portal/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fholzer/nginx-brotli 2 | 3 | COPY ./dist /usr/share/nginx/html 4 | 5 | COPY ./nginx.conf /etc/nginx/nginx.conf 6 | 7 | EXPOSE 9080 8 | -------------------------------------------------------------------------------- /provider/pkg/pconst/pconst.go: -------------------------------------------------------------------------------- 1 | package pconst 2 | 3 | const ( 4 | OperatorClient = "Client" 5 | OperatorRelay = "Relay" 6 | OperatorServer = "Server" 7 | ) 8 | -------------------------------------------------------------------------------- /verifier/app/v1/node/model/mparam/health.go: -------------------------------------------------------------------------------- 1 | package mparam 2 | 3 | type ProviderHealth struct { 4 | OrderID []string `json:"order_id" form:"order_id"` 5 | } 6 | -------------------------------------------------------------------------------- /fullnode/app/v1/user/model/mparam/user.go: -------------------------------------------------------------------------------- 1 | package mparam 2 | 3 | type BindWallet struct { 4 | Wallet string `json:"wallet" form:"wallet" binding:"required"` 5 | } 6 | -------------------------------------------------------------------------------- /contract/artifacts/contracts/CloudSlitDao.sol/CloudSlitDao.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../build-info/e03a705d3196490f8f037dbd0328df0e.json" 4 | } 5 | -------------------------------------------------------------------------------- /portal/src/api/user.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function fetchUser() { 4 | return request({ 5 | url: '/user/detail', 6 | method: 'get' 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /ca/conf.yml: -------------------------------------------------------------------------------- 1 | singleca: 2 | config-path: "./config.json" 3 | 4 | http: 5 | ca-listen: 0.0.0.0:8081 6 | 7 | log: 8 | log-proxy: 9 | host: "" 10 | port: 6379 11 | key: ca_log -------------------------------------------------------------------------------- /portal/src/api/index.js: -------------------------------------------------------------------------------- 1 | export * from './clients' 2 | export * from './servers' 3 | export * from './resource' 4 | export * from './relay' 5 | export * from './user' 6 | export * from './nodes' 7 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../build-info/2cca8ef7664ce8b047a55650f0f82c39.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../build-info/2cca8ef7664ce8b047a55650f0f82c39.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../build-info/2cca8ef7664ce8b047a55650f0f82c39.json" 4 | } 5 | -------------------------------------------------------------------------------- /fullnode/.gitignore: -------------------------------------------------------------------------------- 1 | # ---> Go 2 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 3 | .idea 4 | .DS_Store 5 | .vscode 6 | .docs 7 | 8 | fullnode 9 | logs 10 | release_bin 11 | bin 12 | -------------------------------------------------------------------------------- /ca/util/cert.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "crypto/x509" 4 | 5 | func GetSanURI(cert *x509.Certificate) string { 6 | if len(cert.URIs) > 0 { 7 | return cert.URIs[0].String() 8 | } 9 | return "" 10 | } 11 | -------------------------------------------------------------------------------- /fullnode/examples/helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: FlowShield 3 | kubeVersion: '>=1.16.0-0' 4 | maintainers: 5 | - email: taosheng205054@gmail.com 6 | name: TS 7 | name: FlowShield 8 | version: 0.0.1 9 | -------------------------------------------------------------------------------- /provider/pkg/util/func.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | func InArray(in string, array []string) bool { 4 | for k := range array { 5 | if in == array[k] { 6 | return true 7 | } 8 | } 9 | return false 10 | } 11 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /portal/tests/e2e/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'cypress' 4 | ], 5 | env: { 6 | mocha: true, 7 | 'cypress/globals': true 8 | }, 9 | rules: { 10 | strict: 'off' 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /verifier/verify/options.go: -------------------------------------------------------------------------------- 1 | package verify 2 | 3 | import "time" 4 | 5 | type Options struct { 6 | Often time.Duration 7 | } 8 | 9 | func (o *Options) init() { 10 | if o.Often < 10 { 11 | o.Often = 10 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/pkg/util/structure/structure.go: -------------------------------------------------------------------------------- 1 | package structure 2 | 3 | import ( 4 | "github.com/jinzhu/copier" 5 | ) 6 | 7 | // Copy structure mapping 8 | func Copy(s, ts interface{}) error { 9 | return copier.Copy(ts, s) 10 | } 11 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../build-info/4c809e0b4d7bbe7b2f57732f884ce614.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../../build-info/2cca8ef7664ce8b047a55650f0f82c39.json" 4 | } 5 | -------------------------------------------------------------------------------- /provider/pkg/util/structure/structure.go: -------------------------------------------------------------------------------- 1 | package structure 2 | 3 | import ( 4 | "github.com/jinzhu/copier" 5 | ) 6 | 7 | // Copy structure mapping 8 | func Copy(s, ts interface{}) error { 9 | return copier.Copy(ts, s) 10 | } 11 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /ca/ca/singleca/err.go: -------------------------------------------------------------------------------- 1 | package singleca 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var errBadSigner = errors.New("signer not initialized") 6 | var errNoCertDBConfigured = errors.New("cert database not configured (missing -database-config)") 7 | -------------------------------------------------------------------------------- /portal/src/api/nodes.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取node列表 4 | export function fetchZeroAccessNodes(params = {}) { 5 | return request({ 6 | url: '/node', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /fullnode/examples/helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: zaportal 6 | name: zaportal 7 | spec: 8 | ports: 9 | - port: 80 10 | targetPort: 80 11 | selector: 12 | app: zaportal 13 | -------------------------------------------------------------------------------- /portal/tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/table-of-contents 2 | 3 | describe('My First Test', () => { 4 | it('Visits the app root url', () => { 5 | cy.visit('/') 6 | cy.contains('h1', 'Welcome to Your Vue.js App') 7 | }) 8 | }) 9 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol/ERC20BurnableUpgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /fullnode/test/base64_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | func TestBase64Encode(t *testing.T) { 10 | data := base64.StdEncoding.EncodeToString([]byte("asdasd")) 11 | fmt.Println(data) 12 | } 13 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../../../../../build-info/f2001471b28c74cc8927dc6a797533a1.json" 4 | } 5 | -------------------------------------------------------------------------------- /fullnode/pkg/curl/curl.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | import ( 4 | "os" 5 | "time" 6 | 7 | "github.com/go-resty/resty/v2" 8 | ) 9 | 10 | var Client = resty.New() 11 | 12 | func init() { 13 | if os.Getenv("IDG_RUNTIME") != "production" { 14 | Client.SetDebug(true) 15 | } 16 | Client.SetTimeout(time.Second * 5) 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> Go 2 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 3 | .idea 4 | 5 | fullnode/.idea 6 | fullnode/.DS_Store 7 | fullnode/.vscode 8 | fullnode/.docs 9 | 10 | fullnode/fullnode 11 | fullnode/logs 12 | fullnode/release_bin 13 | fullnode/bin 14 | 15 | verifier/verifier 16 | verifier/logs 17 | -------------------------------------------------------------------------------- /fullnode/app/v1/controlplane/model/mparam/machine.go: -------------------------------------------------------------------------------- 1 | package mparam 2 | 3 | type MachineOauth struct { 4 | Machine string `json:"machine"` 5 | } 6 | 7 | type MachineLongPoll struct { 8 | Category string `json:"category" form:"category" binding:"required"` 9 | Timeout int `json:"timeout" form:"timeout" binding:"required"` 10 | } 11 | -------------------------------------------------------------------------------- /fullnode/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17.8-alpine AS builder 2 | 3 | WORKDIR /build 4 | 5 | COPY . . 6 | 7 | RUN CGO_ENABLED=0 go build -o flowshield . 8 | 9 | 10 | FROM alpine AS final 11 | WORKDIR /app 12 | COPY --from=builder /build/flowshield /app/ 13 | COPY --from=builder /build/config.yaml /app/ 14 | 15 | ENTRYPOINT ["/app/flowshield"] 16 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Context", 4 | "sourceName": "@openzeppelin/contracts/utils/Context.sol", 5 | "abi": [], 6 | "bytecode": "0x", 7 | "deployedBytecode": "0x", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /fullnode/app/v1/node/model/mapi/node.go: -------------------------------------------------------------------------------- 1 | package mapi 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/app/base/mapi" 5 | "github.com/flowshield/flowshield/fullnode/app/v1/node/model/mmysql" 6 | ) 7 | 8 | type NodeList struct { 9 | List []mmysql.Node `json:"list"` 10 | Paginate mapi.AdminPaginate `json:"paginate"` 11 | } 12 | -------------------------------------------------------------------------------- /verifier/route/health/health.go: -------------------------------------------------------------------------------- 1 | package health 2 | 3 | import ( 4 | v1 "github.com/flowshield/flowshield/verifier/app/v1/node/controller" 5 | "github.com/gin-gonic/gin" 6 | ) 7 | 8 | func APIHealth(parentRoute gin.IRouter) { 9 | node := parentRoute.Group("verifier/provider/health") 10 | { 11 | node.POST("", v1.ProviderHealth) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /fullnode/app/v1/access/model/mapi/resource.go: -------------------------------------------------------------------------------- 1 | package mapi 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/app/base/mapi" 5 | "github.com/flowshield/flowshield/fullnode/app/v1/access/model/mmysql" 6 | ) 7 | 8 | type ResourceList struct { 9 | List []mmysql.Resource `json:"list"` 10 | Paginate mapi.AdminPaginate `json:"paginate"` 11 | } 12 | -------------------------------------------------------------------------------- /ca/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .env.rootca 3 | 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | *.DS_Store 18 | 19 | # IDE configs 20 | .idea 21 | .vscode 22 | bin 23 | -------------------------------------------------------------------------------- /fullnode/pkg/logger/config.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | func LogLevel() string { 4 | return "debug" 5 | } 6 | 7 | func LogFile() string { 8 | return LogPath() + LogName() 9 | } 10 | 11 | func SendLogToFile() bool { 12 | return true 13 | } 14 | 15 | func LogPath() string { 16 | return "logs/" 17 | } 18 | 19 | func LogName() string { 20 | return "fullnode.log" 21 | } 22 | -------------------------------------------------------------------------------- /verifier/pkg/logger/config.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | func LogLevel() string { 4 | return "debug" 5 | } 6 | 7 | func LogFile() string { 8 | return LogPath() + LogName() 9 | } 10 | 11 | func SendLogToFile() bool { 12 | return true 13 | } 14 | 15 | func LogPath() string { 16 | return "logs/" 17 | } 18 | 19 | func LogName() string { 20 | return "verifier.log" 21 | } 22 | -------------------------------------------------------------------------------- /portal/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "baseUrl": "./", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@/*": [ 9 | "src/*" 10 | ] 11 | }, 12 | "lib": [ 13 | "esnext", 14 | "dom", 15 | "dom.iterable", 16 | "scripthost" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fullnode/route/node/node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | v1 "github.com/flowshield/flowshield/fullnode/app/v1/node/controller" 5 | "github.com/flowshield/flowshield/fullnode/pkg/middle" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func APINode(parentRoute gin.IRouter) { 10 | node := parentRoute.Group("node", middle.Oauth2()) 11 | { 12 | node.GET("", v1.ListNode) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /fullnode/app/base/mapi/base.go: -------------------------------------------------------------------------------- 1 | package mapi 2 | 3 | type Paginate struct { 4 | Total int `json:"total"` 5 | TotalPage int `json:"total_page"` 6 | CurrentPage int `json:"current_page"` 7 | PrePage int `json:"pre_page"` 8 | } 9 | 10 | type AdminPaginate struct { 11 | Total int64 `json:"total"` 12 | Current int `json:"current"` 13 | PageSize int `json:"pageSize"` 14 | } 15 | -------------------------------------------------------------------------------- /verifier/app/base/mapi/base.go: -------------------------------------------------------------------------------- 1 | package mapi 2 | 3 | type Paginate struct { 4 | Total int `json:"total"` 5 | TotalPage int `json:"total_page"` 6 | CurrentPage int `json:"current_page"` 7 | PrePage int `json:"pre_page"` 8 | } 9 | 10 | type AdminPaginate struct { 11 | Total int64 `json:"total"` 12 | Current int `json:"current"` 13 | PageSize int `json:"pageSize"` 14 | } 15 | -------------------------------------------------------------------------------- /ca/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17.8-alpine AS builder 2 | 3 | ENV GO111MODULE=on 4 | WORKDIR /build 5 | 6 | COPY . . 7 | RUN CGO_ENABLED=0 go build -o ca . 8 | 9 | FROM ubuntu:20.04 10 | 11 | WORKDIR /root 12 | 13 | COPY --from=builder /build/ca . 14 | COPY --from=builder /build/conf.yml . 15 | COPY --from=builder /build/config.json . 16 | RUN chmod +x ca 17 | 18 | # TLS service 19 | CMD ["./ca", "tls"] -------------------------------------------------------------------------------- /fullnode/pkg/middle/cors.go: -------------------------------------------------------------------------------- 1 | package middle 2 | 3 | import ( 4 | "github.com/gin-contrib/cors" 5 | "github.com/gin-gonic/gin" 6 | ) 7 | 8 | // 用于跨域头维护 9 | var corsHeader = []string{""} 10 | 11 | // CorsV2 跨域 12 | func CorsV2() gin.HandlerFunc { 13 | config := cors.DefaultConfig() 14 | config.AllowAllOrigins = true 15 | config.AddAllowHeaders(corsHeader...) 16 | return cors.New(config) 17 | } 18 | -------------------------------------------------------------------------------- /provider/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17.8-alpine AS builder 2 | 3 | WORKDIR /build 4 | 5 | COPY . . 6 | RUN CGO_ENABLED=0 go build -o provider ./cmd 7 | 8 | FROM alpine AS final 9 | 10 | WORKDIR /root 11 | 12 | #RUN apt update && apt install -y curl 13 | 14 | COPY --from=builder /build/provider . 15 | COPY --from=builder /build/configs ./configs 16 | RUN chmod +x provider 17 | 18 | CMD ["./provider"] -------------------------------------------------------------------------------- /verifier/pkg/middle/cors.go: -------------------------------------------------------------------------------- 1 | package middle 2 | 3 | import ( 4 | "github.com/gin-contrib/cors" 5 | "github.com/gin-gonic/gin" 6 | ) 7 | 8 | // 用于跨域头维护 9 | var corsHeader = []string{""} 10 | 11 | // CorsV2 跨域 12 | func CorsV2() gin.HandlerFunc { 13 | config := cors.DefaultConfig() 14 | config.AllowAllOrigins = true 15 | config.AddAllowHeaders(corsHeader...) 16 | return cors.New(config) 17 | } 18 | -------------------------------------------------------------------------------- /verifier/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17.8-alpine AS builder 2 | 3 | ENV GO111MODULE=on \ 4 | GOPROXY=https://goproxy.cn,direct 5 | 6 | WORKDIR /build 7 | 8 | COPY . . 9 | 10 | RUN CGO_ENABLED=0 go build -o verifier . 11 | 12 | 13 | FROM alpine AS final 14 | WORKDIR /app 15 | COPY --from=builder /build/verifier /app/ 16 | COPY --from=builder /build/config.yaml /app/ 17 | 18 | ENTRYPOINT ["/app/verifier"] 19 | -------------------------------------------------------------------------------- /ca/pkg/spiffe/idg_test.go: -------------------------------------------------------------------------------- 1 | package spiffe 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestParseIDGIdentity(t *testing.T) { 9 | cases := []string{ 10 | "spiffe://siteid/clusterid/appid", 11 | "spiffe://test/test/test", 12 | } 13 | for _, a := range cases { 14 | id, err := ParseIDGIdentity(a) 15 | if err != nil { 16 | t.Error(err) 17 | } 18 | fmt.Println(id.String()) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /portal/tests/unit/example.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils' 2 | import HelloWorld from '@/components/HelloWorld.vue' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('renders props.msg when passed', () => { 6 | const msg = 'new message' 7 | const wrapper = shallowMount(HelloWorld, { 8 | propsData: { msg } 9 | }) 10 | expect(wrapper.text()).toMatch(msg) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /ca/util/ip_addr.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | func GetLocalIPs() []string { 8 | addrs, err := net.InterfaceAddrs() 9 | if err != nil { 10 | return nil 11 | } 12 | m := []string{} 13 | for _, addr := range addrs { 14 | if ipnet, ok := addr.(*net.IPNet); ok { 15 | if ip4 := ipnet.IP.To4(); ip4 != nil { 16 | m = append(m, ip4.String()) 17 | } 18 | } 19 | } 20 | return m 21 | } 22 | -------------------------------------------------------------------------------- /portal/vue.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('@vue/cli-service') 2 | module.exports = defineConfig({ 3 | transpileDependencies: [ 4 | 'vuetify' 5 | ] 6 | }) 7 | const NodePolyfillPlugin = require("node-polyfill-webpack-plugin") 8 | module.exports = defineConfig({ 9 | transpileDependencies: true, 10 | configureWebpack: { 11 | plugins: [ 12 | new NodePolyfillPlugin() 13 | ] 14 | } 15 | 16 | }) -------------------------------------------------------------------------------- /client/internal/bll/bll.go: -------------------------------------------------------------------------------- 1 | package bll 2 | 3 | import ( 4 | "io" 5 | "net" 6 | ) 7 | 8 | func TransparentProxy(clientConn, serverConn net.Conn) { 9 | errChan := make(chan error, 2) 10 | copyConn := func(a, b net.Conn) { 11 | _, err := io.Copy(a, b) 12 | errChan <- err 13 | } 14 | go copyConn(clientConn, serverConn) 15 | go copyConn(serverConn, clientConn) 16 | select { 17 | case <-errChan: 18 | return 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /portal/src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuetify from 'vuetify/lib/framework' 3 | 4 | import colors from 'vuetify/lib/util/colors' 5 | 6 | Vue.use(Vuetify) 7 | 8 | export default new Vuetify({ 9 | theme: { 10 | dark: true, 11 | themes: { 12 | light: { 13 | primary: colors.purple 14 | }, 15 | dark: { 16 | primary: colors.purple 17 | } 18 | } 19 | } 20 | }) 21 | -------------------------------------------------------------------------------- /provider/internal/bll/bll.go: -------------------------------------------------------------------------------- 1 | package bll 2 | 3 | import ( 4 | "io" 5 | "net" 6 | ) 7 | 8 | func TransparentProxy(clientConn, serverConn net.Conn) { 9 | errChan := make(chan error, 2) 10 | copyConn := func(a, b net.Conn) { 11 | _, err := io.Copy(a, b) 12 | errChan <- err 13 | } 14 | go copyConn(clientConn, serverConn) 15 | go copyConn(serverConn, clientConn) 16 | select { 17 | case <-errChan: 18 | return 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /verifier/app/v1/node/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/verifier/app/v1/node/model/mparam" 5 | "github.com/flowshield/flowshield/verifier/verify" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func ProviderHealth(c *gin.Context, param *mparam.ProviderHealth) (code int, data map[string]*verify.Record) { 10 | data = verify.VerObj.ProviderHealth(param.OrderID) 11 | return 12 | } 13 | -------------------------------------------------------------------------------- /contract/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | pnpm-debug.log* 18 | 19 | # Editor directories and files 20 | .idea 21 | .vscode 22 | *.suo 23 | *.ntvs* 24 | *.njsproj 25 | *.sln 26 | *.sw? 27 | 28 | #env 29 | .env.development -------------------------------------------------------------------------------- /fullnode/test/key_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/ethereum/go-ethereum/crypto" 8 | ) 9 | 10 | func TestKey(t *testing.T) { 11 | privateKey, err := crypto.HexToECDSA("8828b5d74cdfa86ae17b11d2df83f627a888fab3b86a139c6d442ef7d0e9dd76") 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | address := crypto.PubkeyToAddress(privateKey.PublicKey) 16 | fmt.Println(address.String()) 17 | } 18 | -------------------------------------------------------------------------------- /client/pkg/util/trace/trace.go: -------------------------------------------------------------------------------- 1 | package trace 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "sync/atomic" 7 | "time" 8 | ) 9 | 10 | var ( 11 | version string 12 | incrNum uint64 13 | pid = os.Getpid() 14 | ) 15 | 16 | // NewTraceID New trace id 17 | func NewTraceID() string { 18 | return fmt.Sprintf("trace-id-%d-%s-%d", 19 | os.Getpid(), 20 | time.Now().Format("2006.01.02.15.04.05.999"), 21 | atomic.AddUint64(&incrNum, 1)) 22 | } 23 | -------------------------------------------------------------------------------- /portal/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | pnpm-debug.log* 18 | 19 | # Editor directories and files 20 | .idea 21 | .vscode 22 | *.suo 23 | *.ntvs* 24 | *.njsproj 25 | *.sln 26 | *.sw? 27 | 28 | #env 29 | .env.development 30 | -------------------------------------------------------------------------------- /provider/pkg/util/trace/trace.go: -------------------------------------------------------------------------------- 1 | package trace 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "sync/atomic" 7 | "time" 8 | ) 9 | 10 | var ( 11 | version string 12 | incrNum uint64 13 | pid = os.Getpid() 14 | ) 15 | 16 | // NewTraceID New trace id 17 | func NewTraceID() string { 18 | return fmt.Sprintf("trace-id-%d-%s-%d", 19 | os.Getpid(), 20 | time.Now().Format("2006.01.02.15.04.05.999"), 21 | atomic.AddUint64(&incrNum, 1)) 22 | } 23 | -------------------------------------------------------------------------------- /client/pkg/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | // alias 8 | var ( 9 | New = errors.New 10 | Wrap = errors.Wrap 11 | Wrapf = errors.Wrapf 12 | WithStack = errors.WithStack 13 | WithMessage = errors.WithMessage 14 | WithMessagef = errors.WithMessagef 15 | ) 16 | 17 | var NewWithStack = func(msg string) error { 18 | return errors.WithStack(errors.New(msg)) 19 | } 20 | -------------------------------------------------------------------------------- /provider/pkg/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | // alias 8 | var ( 9 | New = errors.New 10 | Wrap = errors.Wrap 11 | Wrapf = errors.Wrapf 12 | WithStack = errors.WithStack 13 | WithMessage = errors.WithMessage 14 | WithMessagef = errors.WithMessagef 15 | ) 16 | 17 | var NewWithStack = func(msg string) error { 18 | return errors.WithStack(errors.New(msg)) 19 | } 20 | -------------------------------------------------------------------------------- /client/pkg/util/func.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "os" 4 | 5 | func InArray(in string, array []string) bool { 6 | for k := range array { 7 | if in == array[k] { 8 | return true 9 | } 10 | } 11 | return false 12 | } 13 | 14 | func PathExists(path string) (bool, error) { 15 | _, err := os.Stat(path) 16 | if err == nil { 17 | return true, nil 18 | } 19 | if os.IsNotExist(err) { 20 | return false, nil 21 | } 22 | return false, err 23 | } 24 | -------------------------------------------------------------------------------- /fullnode/pkg/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/go-redis/redis/v8" 7 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 8 | ) 9 | 10 | var Client *redis.Client 11 | 12 | func Init(cfg *confer.Redis) (err error) { 13 | Client = redis.NewClient(&redis.Options{ 14 | Addr: cfg.Addr, 15 | }) 16 | if err = Client.Ping(context.Background()).Err(); err != nil { 17 | return 18 | } 19 | return 20 | } 21 | -------------------------------------------------------------------------------- /fullnode/route/controlplane/controlplane.go: -------------------------------------------------------------------------------- 1 | package controlplane 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/flowshield/flowshield/fullnode/app/v1/controlplane/controller" 6 | ) 7 | 8 | func APIControlPlane(parentRoute gin.IRouter) { 9 | controlplane := parentRoute.Group("controlplane") 10 | { 11 | controlplane.GET("/machine/:machine_id", v1.LoginUrl) 12 | controlplane.GET("/machine/auth/poll", v1.MachineLongPoll) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /fullnode/app/base/controller/home.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | func Welcome(c *gin.Context) { 13 | now := time.Now().String() 14 | sysName := confer.ConfigAppGetString("sysname", "default service") 15 | content := fmt.Sprintf("Welcome to %s@%s", sysName, now) 16 | c.String(http.StatusOK, content) 17 | } 18 | -------------------------------------------------------------------------------- /verifier/app/base/controller/home.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/flowshield/flowshield/verifier/pkg/confer" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | func Welcome(c *gin.Context) { 13 | now := time.Now().String() 14 | sysName := confer.ConfigAppGetString("sysname", "default service") 15 | content := fmt.Sprintf("Welcome to %s@%s", sysName, now) 16 | c.String(http.StatusOK, content) 17 | } 18 | -------------------------------------------------------------------------------- /fullnode/app/v1/node/model/mparam/node.go: -------------------------------------------------------------------------------- 1 | package mparam 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/app/base/mdb" 5 | ) 6 | 7 | type ListNode struct { 8 | mdb.Paginate 9 | PeerId string `json:"peer_id" form:"peer_id"` 10 | IP string `json:"ip" form:"ip"` 11 | Loc []string `json:"loc" form:"loc"` 12 | Colo string `json:"colo" form:"colo"` 13 | Price int `json:"price" form:"price"` 14 | Type string `json:"type" form:"type"` 15 | } 16 | -------------------------------------------------------------------------------- /portal/src/utils/cache.js: -------------------------------------------------------------------------------- 1 | export function setCache(k, v) { 2 | const content = JSON.stringify({ 3 | type: typeof v, 4 | value: v 5 | }) 6 | window.localStorage.setItem(k, content) 7 | } 8 | 9 | export function getCache(k, defaultValue) { 10 | const content = window.localStorage.getItem(k) 11 | try { 12 | const obj = JSON.parse(content) 13 | return obj.value 14 | } catch (e) { 15 | return defaultValue === undefined ? content : defaultValue 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fullnode/pkg/middle/session.go: -------------------------------------------------------------------------------- 1 | package middle 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 5 | "github.com/gin-gonic/contrib/sessions" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func Session(name string, cfg *confer.Redis) gin.HandlerFunc { 10 | //return sessions.Sessions(name, sessions.NewCookieStore([]byte("secret"))) 11 | store, _ := sessions.NewRedisStore(10, "tcp", cfg.Addr, "", []byte("secret")) 12 | return sessions.Sessions(name, store) 13 | } 14 | -------------------------------------------------------------------------------- /verifier/config.yaml: -------------------------------------------------------------------------------- 1 | #APP ENV 2 | app: 3 | env: "release" # dev,release 4 | sysname: "FlowShield" 5 | port: 8088 6 | 7 | #Mysql 8 | mysql: 9 | dbname: "zta" 10 | prefix: "zta_" 11 | pool: 12 | pool-min-cap: 10 13 | pool-ex-cap: 5 14 | pool-max-cap: 40 15 | pool-idle-timeout: 3600 16 | pool-wait-count: 1000 17 | pool-wai-timeout: 30 18 | write: 19 | host: "CS_MYSQL_HOST" 20 | port: 23306 21 | user: "CS_MYSQL_USER" 22 | password: "CS_MYSQL_PASSWORD" 23 | -------------------------------------------------------------------------------- /fullnode/pkg/oauth2/option.go: -------------------------------------------------------------------------------- 1 | package oauth2 2 | 3 | import ( 4 | "github.com/gin-gonic/contrib/sessions" 5 | "github.com/gin-gonic/gin" 6 | "github.com/rs/xid" 7 | "golang.org/x/oauth2" 8 | ) 9 | 10 | func GetOauth2RedirectURL(c *gin.Context, config *oauth2.Config) (redirectURL string, err error) { 11 | state := xid.New().String() 12 | redirectURL = config.AuthCodeURL(state, oauth2.ApprovalForce) 13 | session := sessions.Default(c) 14 | session.Set("state", state) 15 | err = session.Save() 16 | return 17 | } 18 | -------------------------------------------------------------------------------- /contract/scripts/upgrade.js: -------------------------------------------------------------------------------- 1 | async function main() { 2 | const proxyAddress = '0x3A35207918FEE0F59a32a1a36B58A758B4F222de'; 3 | 4 | const CloudSlitDaoV2 = await ethers.getContractFactory("CloudSlitDaoV2"); 5 | console.log("Preparing upgrade..."); 6 | 7 | await upgrades.upgradeProxy(proxyAddress, CloudSlitDaoV2); 8 | console.log("Upgraded Successfully"); 9 | } 10 | 11 | main() 12 | .then(() => process.exit(0)) 13 | .catch(error => { 14 | console.error(error); 15 | process.exit(1); 16 | }); -------------------------------------------------------------------------------- /verifier/pkg/confer/config_code.go: -------------------------------------------------------------------------------- 1 | package confer 2 | 3 | import ( 4 | "strconv" 5 | "sync" 6 | ) 7 | 8 | var ( 9 | codeConfig sync.Map 10 | ) 11 | 12 | type ConfigCodeList struct { 13 | Codes map[string]string 14 | } 15 | 16 | func ConfigCodeInit() { 17 | for k, v := range globalConfig.Code { 18 | codeConfig.Store(k, v) 19 | } 20 | } 21 | 22 | func ConfigCodeGetMessage(code int) string { 23 | msg, exists := codeConfig.Load(strconv.Itoa(code)) 24 | if !exists { 25 | return "system error" 26 | } 27 | return msg.(string) 28 | } 29 | -------------------------------------------------------------------------------- /deploy/provider/sqlite_config.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | addr: ":23306" # Network listening address, support MySQL protocol 3 | 4 | sqlite: 5 | filename: "db/sqlite.db" 6 | 7 | debug: # Control to open pprof 8 | enable: false 9 | port: 17878 10 | 11 | # p2p config 12 | p2p: 13 | enable: false 14 | service_discovery_id: "p2p_sqlite_service" 15 | service_command_topic: "p2p_sqlite_service_topic" 16 | service_discover_mode: "advertise" # advertise or announce 17 | 18 | # Tenant list 19 | userlist: 20 | - user: root 21 | password: 123456 22 | -------------------------------------------------------------------------------- /fullnode/route/user/user.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | v1 "github.com/flowshield/flowshield/fullnode/app/v1/user/controller" 5 | "github.com/flowshield/flowshield/fullnode/pkg/middle" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func APIUser(parentRoute gin.IRouter) { 10 | user := parentRoute.Group("user") 11 | { 12 | user.GET("/login", v1.Login) 13 | user.GET("/oauth2/callback", v1.Oauth2Callback) 14 | user.GET("/detail", middle.Oauth2(), v1.UserDetail) 15 | user.POST("/refresh", middle.Oauth2(), v1.UserRefresh) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /portal/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | Artboard 46 2 | -------------------------------------------------------------------------------- /client/pkg/util/uuid/uuid.go: -------------------------------------------------------------------------------- 1 | package uuid 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | // UUID Define alias 8 | type UUID = uuid.UUID 9 | 10 | // NewUUID Create uuid 11 | func NewUUID() (UUID, error) { 12 | return uuid.NewRandom() 13 | } 14 | 15 | // MustUUID Create uuid(Throw panic if something goes wrong) 16 | func MustUUID() UUID { 17 | v, err := NewUUID() 18 | if err != nil { 19 | panic(err) 20 | } 21 | return v 22 | } 23 | 24 | // MustString Create uuid 25 | func MustString() string { 26 | return MustUUID().String() 27 | } 28 | -------------------------------------------------------------------------------- /provider/pkg/util/uuid/uuid.go: -------------------------------------------------------------------------------- 1 | package uuid 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | // UUID Define alias 8 | type UUID = uuid.UUID 9 | 10 | // NewUUID Create uuid 11 | func NewUUID() (UUID, error) { 12 | return uuid.NewRandom() 13 | } 14 | 15 | // MustUUID Create uuid(Throw panic if something goes wrong) 16 | func MustUUID() UUID { 17 | v, err := NewUUID() 18 | if err != nil { 19 | panic(err) 20 | } 21 | return v 22 | } 23 | 24 | // MustString Create uuid 25 | func MustString() string { 26 | return MustUUID().String() 27 | } 28 | -------------------------------------------------------------------------------- /contract/scripts/deploy.js: -------------------------------------------------------------------------------- 1 | async function main() { 2 | const CloudSlitDao = await ethers.getContractFactory("CloudSlitDao"); 3 | console.log("Deploying CloudSlitDao..."); 4 | 5 | const contract = await upgrades.deployProxy(CloudSlitDao, { initializer: 'initialize', kind: "transparent",}); 6 | await contract.deployed(); 7 | console.log("CloudSlitDao deployed to:", contract.address); 8 | } 9 | 10 | main() 11 | .then(() => process.exit(0)) 12 | .catch(error => { 13 | console.error(error); 14 | process.exit(1); 15 | }); -------------------------------------------------------------------------------- /client/internal/machine.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/client/internal/config" 5 | "github.com/flowshield/flowshield/client/pkg/util/uuid" 6 | ) 7 | 8 | // InitMachine initialize the machine id 9 | func InitMachine() error { 10 | machine := config.C.Machine 11 | mac, err := machine.Read() 12 | if err != nil { 13 | machine.SetMachineId(uuid.MustString()) 14 | err = machine.Write() 15 | if err != nil { 16 | return err 17 | } 18 | } else { 19 | machine.SetMachineId(mac.MachineId) 20 | machine.SetCookie(mac.Cookie) 21 | } 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /verifier/config_dev.yaml: -------------------------------------------------------------------------------- 1 | #APP ENV 2 | app: 3 | env: "release" # dev,release 4 | sysname: "FlowShield" 5 | port: 80 6 | 7 | #Mysql 8 | mysql: 9 | dbname: "zta" 10 | prefix: "zta_" 11 | pool: 12 | pool-min-cap: 10 13 | pool-ex-cap: 5 14 | pool-max-cap: 40 15 | pool-idle-timeout: 3600 16 | pool-wait-count: 1000 17 | pool-wai-timeout: 30 18 | write: 19 | host: "38.96.139.114:33306" 20 | port: 33306 21 | user: "root" 22 | password: "123456" 23 | # write: 24 | # host: "192.168.2.80:3306" 25 | # port: 3306 26 | # user: "root" 27 | # password: "123456" 28 | -------------------------------------------------------------------------------- /client/internal/contextx/contextx.go: -------------------------------------------------------------------------------- 1 | package contextx 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type ( 8 | traceIDCtx struct{} 9 | ) 10 | 11 | // NewTraceID Create a context to trace the ID 12 | func NewTraceID(ctx context.Context, traceID string) context.Context { 13 | return context.WithValue(ctx, traceIDCtx{}, traceID) 14 | } 15 | 16 | // FromTraceID gets the trace id from the context 17 | func FromTraceID(ctx context.Context) (string, bool) { 18 | v := ctx.Value(traceIDCtx{}) 19 | if v != nil { 20 | if s, ok := v.(string); ok { 21 | return s, s != "" 22 | } 23 | } 24 | return "", false 25 | } 26 | -------------------------------------------------------------------------------- /client/internal/schema/schema.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | // StatusText Define status text 4 | type StatusText string 5 | 6 | func (t StatusText) String() string { 7 | return string(t) 8 | } 9 | 10 | // NextServer 11 | type NextServer struct { 12 | Host string 13 | Port string 14 | } 15 | 16 | // ControlCommonResult 17 | type ControlCommonResult struct { 18 | Code int `json:"code"` 19 | Message string `json:"message"` 20 | } 21 | 22 | // ControlPaginate 23 | type ControlPaginate struct { 24 | Total int `json:"total"` 25 | Current int `json:"current"` 26 | PageSize int `json:"pageSize"` 27 | } 28 | -------------------------------------------------------------------------------- /provider/internal/schema/schema.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | // StatusText Define status text 4 | type StatusText string 5 | 6 | func (t StatusText) String() string { 7 | return string(t) 8 | } 9 | 10 | // NextServer 11 | type NextServer struct { 12 | Host string 13 | Port string 14 | } 15 | 16 | // ControlCommonResult 17 | type ControlCommonResult struct { 18 | Code int `json:"code"` 19 | Message string `json:"message"` 20 | } 21 | 22 | // ControlPaginate 23 | type ControlPaginate struct { 24 | Total int `json:"total"` 25 | Current int `json:"current"` 26 | PageSize int `json:"pageSize"` 27 | } 28 | -------------------------------------------------------------------------------- /provider/internal/contextx/contextx.go: -------------------------------------------------------------------------------- 1 | package contextx 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type ( 8 | traceIDCtx struct{} 9 | ) 10 | 11 | // NewTraceID Create a context to trace the ID 12 | func NewTraceID(ctx context.Context, traceID string) context.Context { 13 | return context.WithValue(ctx, traceIDCtx{}, traceID) 14 | } 15 | 16 | // FromTraceID gets the trace id from the context 17 | func FromTraceID(ctx context.Context) (string, bool) { 18 | v := ctx.Value(traceIDCtx{}) 19 | if v != nil { 20 | if s, ok := v.(string); ok { 21 | return s, s != "" 22 | } 23 | } 24 | return "", false 25 | } 26 | -------------------------------------------------------------------------------- /fullnode/examples/helm/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | {{- range $key, $value := .Values.ingress.annotations }} 6 | {{ $key }}: {{ tpl $value $ | quote }} 7 | {{- end }} 8 | labels: 9 | app: zaportal 10 | name: zaportal 11 | spec: 12 | rules: 13 | - host: {{ .Values.ingress.host }} 14 | http: 15 | paths: 16 | - path: / 17 | backend: 18 | serviceName: zaportal 19 | servicePort: 80 20 | tls: 21 | - hosts: 22 | - {{ .Values.ingress.host }} 23 | secretName: zaportal-tls 24 | -------------------------------------------------------------------------------- /ca/util/cache.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/hex" 6 | "math" 7 | "strconv" 8 | "time" 9 | 10 | "github.com/flowshield/flowshield/ca/pkg/memorycacher" 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | var MapCache *memorycacher.Cache 15 | 16 | func init() { 17 | MapCache = memorycacher.New(2*time.Minute, 10*time.Minute, math.MaxInt64) 18 | } 19 | 20 | func GinRequestHash(g *gin.Context) string { 21 | url := g.Request.URL.String() 22 | body := g.Request.ContentLength 23 | 24 | sha := sha1.Sum([]byte(url + strconv.FormatInt(body, 10))) 25 | 26 | return hex.EncodeToString(sha[:]) 27 | } 28 | -------------------------------------------------------------------------------- /portal/docs/docker.md: -------------------------------------------------------------------------------- 1 | # Docker 2 | 3 | ## Docker build 4 | 5 | ```bash 6 | docker build -t rovast/za-portal . 7 | ``` 8 | 9 | ## Run 10 | 11 | ```bash 12 | docker run --name zaportal -p 9080:9080 -d rovast/za-portal:latest 13 | ``` 14 | 15 | You can visit http://127.0.0.1:9080 16 | 17 | ## Settings 18 | 19 | ### Expose ports 20 | 21 | - 9080: frontend port 22 | - 80: backend port 23 | 24 | > Frontend will request `/api`, and will proxy by nginx, you can config it in `nginx.conf` 25 | 26 | ### Nginx configuration 27 | 28 | - conf file: `/etc/nginx/nginx.conf` 29 | - frontend dist path(www root): `/usr/share/nginx/html` 30 | 31 | -------------------------------------------------------------------------------- /ca/core/state.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/flowshield/flowshield/ca/core/config" 7 | "github.com/flowshield/flowshield/ca/pkg/logger" 8 | "gorm.io/gorm" 9 | ) 10 | 11 | // Config ... 12 | type Config struct { 13 | config.IConfig 14 | } 15 | 16 | // Is ... 17 | var Is *I 18 | 19 | // Elector ... 20 | type Elector interface { 21 | IsLeader() bool 22 | } 23 | 24 | // Logger ... 25 | type Logger struct { 26 | *logger.Logger 27 | } 28 | 29 | // I ... 30 | type I struct { 31 | Ctx context.Context 32 | Config *Config 33 | Logger *Logger 34 | Db *gorm.DB 35 | Elector Elector 36 | } 37 | -------------------------------------------------------------------------------- /fullnode/test/json_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/tidwall/gjson" 9 | ) 10 | 11 | type Person struct { 12 | FirstName string `json:"first"` 13 | LastName string `json:"last"` 14 | } 15 | 16 | func TestJson(t *testing.T) { 17 | const jsonStr = `{"name":{"first":"Janet","last":"Prichard"},"age":47}` 18 | value := gjson.Get(jsonStr, "name") 19 | var person Person 20 | json.Unmarshal([]byte(value.String()), &person) 21 | fmt.Println(person) 22 | } 23 | 24 | func TestString(t *testing.T) { 25 | var str = "abcdefg" 26 | fmt.Println(str[len(str)-2:]) 27 | } 28 | -------------------------------------------------------------------------------- /fullnode/app/base/controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/flowshield/flowshield/fullnode/pconst" 6 | "github.com/flowshield/flowshield/fullnode/pkg/logger" 7 | ) 8 | 9 | type Res struct { 10 | Code int `json:"code"` 11 | Data struct{} `json:"data"` 12 | Msg string `json:"message"` 13 | } 14 | 15 | func BindParams(c *gin.Context, params interface{}) (b bool, code int) { 16 | err := c.ShouldBind(params) 17 | if err != nil { 18 | logger.Warnf(c, "params error: %v", err) 19 | code = pconst.CODE_COMMON_PARAMS_INCOMPLETE 20 | return 21 | } 22 | b = true 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /verifier/app/base/controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/verifier/pconst" 5 | "github.com/flowshield/flowshield/verifier/pkg/logger" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | type Res struct { 10 | Code int `json:"code"` 11 | Data struct{} `json:"data"` 12 | Msg string `json:"message"` 13 | } 14 | 15 | func BindParams(c *gin.Context, params interface{}) (b bool, code int) { 16 | err := c.ShouldBind(params) 17 | if err != nil { 18 | logger.Warnf(c, "params error: %v", err) 19 | code = pconst.CODE_COMMON_PARAMS_INCOMPLETE 20 | return 21 | } 22 | b = true 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /portal/src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | // import qs from 'qs' 3 | import { requestInterceptors } from './request-helper' 4 | 5 | // create an axios instance 6 | const service = axios.create({ 7 | baseURL: process.env.VUE_APP_BASE_URL, 8 | // withCredentials: false, // send cookies when cross-domain requests 9 | // transformRequest: [function(data, headers) { 10 | // return qs.stringify(data) 11 | // }], 12 | // paramsSerializer: function(params) { 13 | // return qs.stringify(params, { indices: false }) 14 | // }, 15 | timeout: 50000 // request timeout 16 | }) 17 | 18 | requestInterceptors(service) 19 | 20 | export default service 21 | -------------------------------------------------------------------------------- /fullnode/app/v1/access/model/mmysql/resource.go: -------------------------------------------------------------------------------- 1 | package mmysql 2 | 3 | type Resource struct { 4 | ID uint `gorm:"primarykey"` 5 | CreatedAt int64 `gorm:"autoCreateTime"` 6 | UpdatedAt int64 `gorm:"autoUpdateTime"` 7 | Name string `json:"name"` 8 | UUID string `json:"uuid" gorm:"column:uuid"` 9 | UserUUID string `json:"user_uuid" gorm:"user_uuid"` 10 | Type string `json:"type"` 11 | Host string `json:"host"` // api.github.com 12 | Port string `json:"port" gorm:"column:port"` // 80-443;3306;6379 13 | Cid string `json:"cid"` 14 | } 15 | 16 | func (Resource) TableName() string { 17 | return "zta_resource" 18 | } 19 | -------------------------------------------------------------------------------- /verifier/server/http.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/flowshield/flowshield/verifier/pkg/confer" 8 | "github.com/flowshield/flowshield/verifier/pkg/gin" 9 | "github.com/flowshield/flowshield/verifier/pkg/middle" 10 | "github.com/flowshield/flowshield/verifier/route" 11 | ) 12 | 13 | func RunHTTP() { 14 | engine := gin.NewGin() 15 | // 跨域中间件 16 | engine.Use(middle.CorsV2()) 17 | route.Home(engine) 18 | route.Api(engine) 19 | route.NotFound(engine) 20 | httpPort := confer.ConfigAppGetInt("port", 80) 21 | portStr := ":" + strconv.Itoa(httpPort) 22 | fmt.Println("start", httpPort) 23 | gin.ListenHTTP(portStr, engine, 10) 24 | } 25 | -------------------------------------------------------------------------------- /ca/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all build clean 2 | 3 | PROG=bin/ca 4 | SRCS=. 5 | 6 | # git commit hash 7 | COMMIT_HASH=$(shell git rev-parse --short HEAD || echo "GitNotFound") 8 | # Compilation date 9 | BUILD_DATE=$(shell date '+%Y-%m-%d %H:%M:%S') 10 | # Compilation conditions 11 | CFLAGS = -ldflags "-s -w -X \"main.BuildVersion=${COMMIT_HASH}\" -X \"main.BuildDate=$(BUILD_DATE)\"" 12 | 13 | all: 14 | if [ ! -d "./bin/" ]; then \ 15 | mkdir bin; \ 16 | fi 17 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(CFLAGS) -o $(PROG) $(SRCS) 18 | 19 | build: 20 | go build -race -tags=jsoniter 21 | 22 | compose: 23 | sudo docker-compose up -d 24 | 25 | run: 26 | go run main.go 27 | 28 | clean: 29 | rm -rf ./bin -------------------------------------------------------------------------------- /fullnode/app/v1/user/model/mmysql/user.go: -------------------------------------------------------------------------------- 1 | package mmysql 2 | 3 | const ( 4 | UnBind = iota 5 | Bind 6 | ) 7 | 8 | type User struct { 9 | ID uint `gorm:"primarykey"` 10 | CreatedAt int64 `gorm:"autoCreateTime"` 11 | UpdatedAt int64 `gorm:"autoUpdateTime"` 12 | Email string `json:"email"` 13 | AvatarUrl string `json:"avatar_url"` 14 | UUID string `json:"uuid" gorm:"column:uuid"` 15 | //Wallet string `json:"wallet"` 16 | Status int `json:"status"` // 0 未绑定 1 已绑定 17 | Master bool `json:"master" gorm:"-"` // 判断当前用户是否Dao主 18 | Provider bool `json:"provider" gorm:"-"` // 判断当前用户是否Provider 19 | } 20 | 21 | func (User) TableName() string { 22 | return "zta_user" 23 | } 24 | -------------------------------------------------------------------------------- /portal/src/api/servers.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function fetchZeroAccessServers(params = {}) { 4 | return request({ 5 | url: '/access/server', 6 | method: 'get', 7 | params 8 | }) 9 | } 10 | 11 | export function postZeroAccessServer(data = {}) { 12 | return request({ 13 | url: '/access/server', 14 | method: 'post', 15 | data 16 | }) 17 | } 18 | 19 | export function putZeroAccessServer(data = {}) { 20 | return request({ 21 | url: '/access/server', 22 | method: 'put', 23 | data 24 | }) 25 | } 26 | 27 | export function deleteZeroAccessServer(id) { 28 | return request({ 29 | url: `/access/server/${id}`, 30 | method: 'delete' 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Initializable", 4 | "sourceName": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": false, 11 | "internalType": "uint8", 12 | "name": "version", 13 | "type": "uint8" 14 | } 15 | ], 16 | "name": "Initialized", 17 | "type": "event" 18 | } 19 | ], 20 | "bytecode": "0x", 21 | "deployedBytecode": "0x", 22 | "linkReferences": {}, 23 | "deployedLinkReferences": {} 24 | } 25 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "ContextUpgradeable", 4 | "sourceName": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": false, 11 | "internalType": "uint8", 12 | "name": "version", 13 | "type": "uint8" 14 | } 15 | ], 16 | "name": "Initialized", 17 | "type": "event" 18 | } 19 | ], 20 | "bytecode": "0x", 21 | "deployedBytecode": "0x", 22 | "linkReferences": {}, 23 | "deployedLinkReferences": {} 24 | } 25 | -------------------------------------------------------------------------------- /ca/pkg/logger/redis_hook/loggers.go: -------------------------------------------------------------------------------- 1 | package redis_hook 2 | 3 | import ( 4 | "go.uber.org/zap/zapcore" 5 | "strings" 6 | ) 7 | 8 | // zap need extra data for fields 9 | func CreateZapOriginLogMessage(entry *zapcore.Entry, data map[string]interface{}) map[string]interface{} { 10 | fields := make(map[string]interface{}, len(data)) 11 | if data != nil { 12 | for k, v := range data { 13 | fields[k] = v 14 | } 15 | } 16 | var level = strings.ToUpper(entry.Level.String()) 17 | if level == "ERROR" { 18 | level = "ERR" 19 | } 20 | if level == "WARN" { 21 | level = "WARNING" 22 | } 23 | if level == "FATAL" { 24 | level = "CRIT" 25 | } 26 | fields["level"] = level 27 | fields["message"] = entry.Message 28 | return fields 29 | } 30 | -------------------------------------------------------------------------------- /verifier/verify/record.go: -------------------------------------------------------------------------------- 1 | package verify 2 | 3 | import "sync/atomic" 4 | 5 | type Record struct { 6 | Total uint64 `json:"total"` 7 | Success uint64 `json:"success"` 8 | Fail uint64 `json:"fail"` 9 | } 10 | 11 | func (r *Record) AddSuccess(num uint64) { 12 | atomic.AddUint64(&r.Fail, num) 13 | atomic.AddUint64(&r.Total, num) 14 | } 15 | 16 | func (r *Record) AddFail(num uint64) { 17 | atomic.AddUint64(&r.Fail, num) 18 | atomic.AddUint64(&r.Total, num) 19 | } 20 | 21 | func (r *Record) GetFail() uint64 { 22 | return atomic.LoadUint64(&r.Fail) 23 | } 24 | 25 | func (r *Record) GetSuccess() uint64 { 26 | return atomic.LoadUint64(&r.Success) 27 | } 28 | 29 | func (r *Record) GetTotal() uint64 { 30 | return atomic.LoadUint64(&r.Total) 31 | } 32 | -------------------------------------------------------------------------------- /client/pkg/util/json/json.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | jsoniter "github.com/json-iterator/go" 5 | ) 6 | 7 | // Defining JSON operations 8 | var ( 9 | json = jsoniter.ConfigCompatibleWithStandardLibrary 10 | Marshal = json.Marshal 11 | Unmarshal = json.Unmarshal 12 | MarshalIndent = json.MarshalIndent 13 | NewDecoder = json.NewDecoder 14 | NewEncoder = json.NewEncoder 15 | ) 16 | 17 | func MarshalToString(v interface{}) string { 18 | s, err := jsoniter.MarshalToString(v) 19 | if err != nil { 20 | return "" 21 | } 22 | return s 23 | } 24 | 25 | func UnmarshalFromString(str string, v interface{}) error { 26 | err := jsoniter.UnmarshalFromString(str, v) 27 | if err != nil { 28 | return err 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /fullnode/pkg/util/json/json.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | jsoniter "github.com/json-iterator/go" 5 | ) 6 | 7 | // Defining JSON operations 8 | var ( 9 | json = jsoniter.ConfigCompatibleWithStandardLibrary 10 | Marshal = json.Marshal 11 | Unmarshal = json.Unmarshal 12 | MarshalIndent = json.MarshalIndent 13 | NewDecoder = json.NewDecoder 14 | NewEncoder = json.NewEncoder 15 | ) 16 | 17 | func MarshalToString(v interface{}) string { 18 | s, err := jsoniter.MarshalToString(v) 19 | if err != nil { 20 | return "" 21 | } 22 | return s 23 | } 24 | 25 | func UnmarshalFromString(str string, v interface{}) error { 26 | err := jsoniter.UnmarshalFromString(str, v) 27 | if err != nil { 28 | return err 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /provider/pkg/util/json/json.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | jsoniter "github.com/json-iterator/go" 5 | ) 6 | 7 | // Defining JSON operations 8 | var ( 9 | json = jsoniter.ConfigCompatibleWithStandardLibrary 10 | Marshal = json.Marshal 11 | Unmarshal = json.Unmarshal 12 | MarshalIndent = json.MarshalIndent 13 | NewDecoder = json.NewDecoder 14 | NewEncoder = json.NewEncoder 15 | ) 16 | 17 | func MarshalToString(v interface{}) string { 18 | s, err := jsoniter.MarshalToString(v) 19 | if err != nil { 20 | return "" 21 | } 22 | return s 23 | } 24 | 25 | func UnmarshalFromString(str string, v interface{}) error { 26 | err := jsoniter.UnmarshalFromString(str, v) 27 | if err != nil { 28 | return err 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /portal/src/api/relay.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取relay列表 4 | export function fetchZeroAccessRelays(params = {}) { 5 | return request({ 6 | url: '/access/relay', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | 12 | // 添加relay 13 | export function postZeroAccessRelay(data = {}) { 14 | return request({ 15 | url: '/access/relay', 16 | method: 'post', 17 | data 18 | }) 19 | } 20 | 21 | // 修改relay 22 | export function putZeroAccessRelay(data = {}) { 23 | return request({ 24 | url: '/access/relay', 25 | method: 'put', 26 | data 27 | }) 28 | } 29 | 30 | // 删除relay 31 | export function deleteZeroAccessRelay(id) { 32 | return request({ 33 | url: `/access/relay/${id}`, 34 | method: 'delete' 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /portal/tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /ca/pkg/logger/logger_test.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "go.uber.org/zap/zapcore" 6 | "testing" 7 | ) 8 | 9 | func TestNewLogger(t *testing.T) { 10 | defer Sync() 11 | GlobalConfig(Conf{ 12 | Debug: true, 13 | Caller: true, 14 | AppInfo: &ConfigAppData{ 15 | AppName: "test", 16 | AppID: "test", 17 | AppVersion: "1.0", 18 | AppKey: "test", 19 | Channel: "1", 20 | SubOrgKey: "key", 21 | Language: "zh", 22 | }, 23 | }) 24 | S().Info("test") 25 | } 26 | 27 | func TestColorLogger(t *testing.T) { 28 | config := zap.NewDevelopmentConfig() 29 | config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder 30 | logger, _ := config.Build() 31 | 32 | logger.Info("Now logs should be colored") 33 | } 34 | -------------------------------------------------------------------------------- /client/internal/schema/s_server.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import "github.com/flowshield/flowshield/client/pkg/util/json" 4 | 5 | type ServerType string 6 | 7 | const ServerTypeProvider ServerType = "provider" 8 | 9 | type ServerInfo struct { 10 | PeerAddress string `json:"peer_address"` 11 | PeerId string `json:"peer_id"` 12 | Addr string `json:"addr"` 13 | Port int `json:"port"` 14 | MetaData MetaData `json:"meta_data"` 15 | GasPrice int `json:"price"` 16 | Type ServerType `json:"type"` 17 | } 18 | 19 | type MetaData struct { 20 | Ip string `json:"ip"` 21 | Loc string `json:"loc"` 22 | Colo string `json:"colo"` 23 | } 24 | 25 | func (a *ServerInfo) String() string { 26 | return json.MarshalToString(a) 27 | } 28 | -------------------------------------------------------------------------------- /verifier/route/route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/verifier/app/base/controller" 5 | "github.com/flowshield/flowshield/verifier/pconst" 6 | "github.com/flowshield/flowshield/verifier/pkg/confer" 7 | "github.com/flowshield/flowshield/verifier/route/health" 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | // Home 主页 12 | func Home(engine *gin.Engine) { 13 | engine.GET("", controller.Welcome) 14 | } 15 | 16 | func Api(engine *gin.Engine) { 17 | prefix := confer.ConfigAppGetString("UrlPrefix", "") 18 | RouteV1 := engine.Group(prefix + pconst.APIAPIV1URL) 19 | { 20 | health.APIHealth(RouteV1) 21 | } 22 | } 23 | 24 | func NotFound(r *gin.Engine) { 25 | r.NoRoute(func(c *gin.Context) { 26 | c.String(404, "404 Not Found") 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /verifier/server/init.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/verifier/pkg/confer" 5 | "github.com/flowshield/flowshield/verifier/pkg/logger" 6 | "github.com/flowshield/flowshield/verifier/pkg/mysql" 7 | "github.com/urfave/cli" 8 | ) 9 | 10 | func InitService(c *cli.Context) (err error) { 11 | if err = confer.Init(c.String("c")); err != nil { 12 | return 13 | } 14 | cfg := confer.GlobalConfig() 15 | logger.Init(&logger.Config{ 16 | Level: logger.LogLevel(), 17 | Filename: logger.LogFile(), 18 | SendToFile: logger.SendLogToFile(), 19 | Development: confer.ConfigEnvIsDev(), 20 | }) 21 | if err = mysql.Init(&cfg.Mysql); err != nil { 22 | logger.Errorf(nil, "mysql init error : %v", err) 23 | return 24 | } 25 | return 26 | } 27 | -------------------------------------------------------------------------------- /fullnode/pkg/schema/s_server.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | type ServerType string 4 | 5 | const ServerTypeProvider ServerType = "provider" 6 | 7 | const FullNode ServerType = "fullnode" 8 | 9 | type ServerInfo struct { 10 | PeerId string `json:"peer_id"` 11 | Addr string `json:"addr"` 12 | Port int `json:"port"` 13 | MetaData MetaData `json:"meta_data"` 14 | Price uint `json:"price"` 15 | Type ServerType `json:"type"` 16 | } 17 | 18 | type MetaData struct { 19 | Ip string `json:"ip"` 20 | Loc string `json:"loc"` 21 | Colo string `json:"colo"` 22 | } 23 | 24 | type ClientP2P struct { 25 | ServerCID string `json:"server_cid"` 26 | Wallet string `json:"wallet"` 27 | UUID string `json:"uuid"` 28 | Port int `json:"port"` 29 | } 30 | -------------------------------------------------------------------------------- /portal/src/api/resource.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取资源列表 4 | export function fetchZeroAccessResources(params = {}) { 5 | return request({ 6 | url: '/access/resource', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | 12 | // 添加资源 13 | export function postZeroAccessResource(data = {}) { 14 | return request({ 15 | url: '/access/resource', 16 | method: 'post', 17 | data 18 | }) 19 | } 20 | 21 | // 修改资源 22 | export function putZeroAccessResource(data = {}) { 23 | return request({ 24 | url: '/access/resource', 25 | method: 'put', 26 | data 27 | }) 28 | } 29 | 30 | // 删除资源 31 | export function deleteZeroAccessResource(id) { 32 | return request({ 33 | url: `/access/resource/${id}`, 34 | method: 'delete' 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/flowshield/flowshield/client 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/LyricTian/queue v1.3.0 7 | github.com/fatih/camelcase v1.0.0 // indirect 8 | github.com/fatih/structs v1.1.0 // indirect 9 | github.com/go-redis/redis v6.15.9+incompatible 10 | github.com/google/uuid v1.6.0 11 | github.com/ipfs/go-cid v0.4.1 12 | github.com/jinzhu/copier v0.4.0 13 | github.com/json-iterator/go v1.1.12 14 | github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7 15 | github.com/onsi/gomega v1.19.0 // indirect 16 | github.com/pkg/errors v0.9.1 17 | github.com/sirupsen/logrus v1.9.3 18 | github.com/urfave/cli/v2 v2.27.3 19 | github.com/web3-storage/go-w3s-client v0.0.7 20 | github.com/wumansgy/goEncrypt v1.0.0 21 | github.com/xtaci/smux v2.0.1+incompatible 22 | ) 23 | -------------------------------------------------------------------------------- /contract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "contract", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@nomicfoundation/hardhat-toolbox": "^2.0.0", 14 | "@nomiclabs/hardhat-ethers": "^2.0.6", 15 | "@nomiclabs/hardhat-waffle": "^2.0.3", 16 | "chai": "^4.3.6", 17 | "ethereum-waffle": "^3.4.4", 18 | "ethers": "^5.6.9", 19 | "hardhat": "^2.10.0" 20 | }, 21 | "dependencies": { 22 | "@openzeppelin/contracts": "^4.7.0", 23 | "@openzeppelin/contracts-upgradeable": "^4.7.2", 24 | "@openzeppelin/hardhat-upgrades": "^1.19.1", 25 | "dotenv": "^16.0.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fullnode/app/v1/user/dao/api/github.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "io/ioutil" 7 | 8 | "github.com/gin-gonic/gin" 9 | "github.com/google/go-github/github" 10 | "golang.org/x/oauth2" 11 | ) 12 | 13 | func GetGithubUser(c *gin.Context, config *oauth2.Config, code string) (user *github.User, err error) { 14 | token, err := config.Exchange(c, code) 15 | if err != nil { 16 | return 17 | } 18 | client := config.Client(context.TODO(), token) 19 | response, err := client.Get("https://api.github.com/user") 20 | if err != nil { 21 | return 22 | } 23 | defer response.Body.Close() 24 | info, err := ioutil.ReadAll(response.Body) 25 | if err != nil { 26 | return 27 | } 28 | err = json.Unmarshal(info, &user) 29 | if err != nil { 30 | return 31 | } 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /ca/pkg/signature/signer_test.go: -------------------------------------------------------------------------------- 1 | package signature 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "fmt" 6 | "github.com/flowshield/flowshield/ca/pkg/keygen" 7 | "testing" 8 | ) 9 | 10 | func TestEcdsaSign(t *testing.T) { 11 | priv, _, _ := keygen.GenKey(keygen.EcdsaSigAlg) 12 | s := NewSigner(priv) 13 | sign, err := s.Sign([]byte("Test")) 14 | if err != nil { 15 | panic(err) 16 | } 17 | fmt.Println(sign) 18 | } 19 | 20 | func TestEcdsaVerify(t *testing.T) { 21 | text := []byte("Test") 22 | priv, _, _ := keygen.GenKey(keygen.EcdsaSigAlg) 23 | s := NewSigner(priv) 24 | sign, err := s.Sign(text) 25 | if err != nil { 26 | panic(err) 27 | } 28 | key := priv.(*ecdsa.PrivateKey) 29 | v := NewVerifier(key.Public()) 30 | result, err := v.Verify(text, sign) 31 | if err != nil { 32 | panic(err) 33 | } 34 | fmt.Println(result) 35 | } 36 | -------------------------------------------------------------------------------- /ca/initer/initer.go: -------------------------------------------------------------------------------- 1 | package initer 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/ca/ca/keymanager" 5 | "github.com/flowshield/flowshield/ca/core" 6 | "github.com/flowshield/flowshield/ca/pkg/logger" 7 | "github.com/urfave/cli" 8 | "log" 9 | // ... 10 | _ "github.com/flowshield/flowshield/ca/util" 11 | ) 12 | 13 | // Init Initialization 14 | func Init(c *cli.Context) error { 15 | conf, err := parseConfigs(c) 16 | if err != nil { 17 | return err 18 | } 19 | initLogger(&conf) 20 | log.Printf("started with conf: %+v", conf) 21 | 22 | l := &core.Logger{Logger: logger.S()} 23 | 24 | i := &core.I{ 25 | Config: &conf, 26 | Logger: l, 27 | } 28 | 29 | core.Is = i 30 | // CA Start 31 | if err := keymanager.InitKeeper(); err != nil { 32 | return err 33 | } 34 | 35 | logger.Info("success started.") 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /provider/pkg/web3/eth/eth.go: -------------------------------------------------------------------------------- 1 | package eth 2 | 3 | import ( 4 | "context" 5 | "math/big" 6 | 7 | "github.com/flowshield/flowshield/provider/internal/config" 8 | 9 | "github.com/ethereum/go-ethereum/common" 10 | 11 | "github.com/ethereum/go-ethereum/ethclient" 12 | ) 13 | 14 | var client *ethclient.Client 15 | 16 | func Init(cfg *config.Web3) (err error) { 17 | client, err = ethclient.Dial(cfg.EthAddress()) 18 | if err != nil { 19 | return err 20 | } 21 | return nil 22 | } 23 | 24 | func GetEthBalance(ctx context.Context, address string) (*big.Int, error) { 25 | account := common.HexToAddress(address) 26 | balance, err := client.BalanceAt(ctx, account, nil) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return balance, nil 31 | } 32 | 33 | func GetContractBalance(address string) (*big.Int, error) { 34 | return nil, nil 35 | } 36 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Basic set up for three package managers 2 | 3 | version: 2 4 | updates: 5 | 6 | # Maintain dependencies for GitHub Actions 7 | - package-ecosystem: "github-actions" 8 | directory: "/" 9 | schedule: 10 | interval: "daily" 11 | 12 | # Maintain dependencies for gomod 13 | - package-ecosystem: "gomod" 14 | directory: "/client" 15 | schedule: 16 | interval: "daily" 17 | 18 | - package-ecosystem: "gomod" 19 | directory: "/fullnode" 20 | schedule: 21 | interval: "daily" 22 | 23 | - package-ecosystem: "gomod" 24 | directory: "/provider" 25 | schedule: 26 | interval: "daily" 27 | 28 | - package-ecosystem: "gomod" 29 | directory: "/verifier" 30 | schedule: 31 | interval: "daily" 32 | 33 | - package-ecosystem: "gomod" 34 | directory: "/ca" 35 | schedule: 36 | interval: "daily" -------------------------------------------------------------------------------- /verifier/app/v1/node/controller/health.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/verifier/app/base/controller" 5 | "github.com/flowshield/flowshield/verifier/app/v1/node/model/mparam" 6 | "github.com/flowshield/flowshield/verifier/app/v1/node/service" 7 | "github.com/flowshield/flowshield/verifier/pkg/response" 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | // @Summary ListNode 12 | // @Description 获取全部节点 13 | // @Tags ZTA Node 14 | // @Produce json 15 | // @Success 200 {object} controller.Res 16 | // @Router /verifier/provider/health [post] 17 | func ProviderHealth(c *gin.Context) { 18 | param := &mparam.ProviderHealth{} 19 | b, code := controller.BindParams(c, ¶m) 20 | if !b { 21 | response.UtilResponseReturnJsonFailed(c, code) 22 | return 23 | } 24 | code, data := service.ProviderHealth(c, param) 25 | response.UtilResponseReturnJson(c, code, data) 26 | } 27 | -------------------------------------------------------------------------------- /portal/src/api/clients.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function fetchZeroAccessClients(params = {}) { 4 | return request({ 5 | url: '/access/client', 6 | method: 'get', 7 | params 8 | }) 9 | } 10 | 11 | export function postZeroAccessClientsPayNotify(data = {}) { 12 | return request({ 13 | url: '/access/client/notify', 14 | method: 'post', 15 | data 16 | }) 17 | } 18 | export function postZeroAccessClient(data = {}) { 19 | return request({ 20 | url: '/access/client', 21 | method: 'post', 22 | data 23 | }) 24 | } 25 | 26 | export function putZeroAccessClient(data = {}) { 27 | return request({ 28 | url: '/access/client', 29 | method: 'put', 30 | data 31 | }) 32 | } 33 | 34 | export function deleteZeroAccessClient(id) { 35 | return request({ 36 | url: `/access/client/${id}`, 37 | method: 'delete' 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "AddressUpgradeable", 4 | "sourceName": "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", 5 | "abi": [], 6 | "bytecode": "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220f27157671d3c5868c24716171f9097885f02c47048143a1215c481954d38a6b164736f6c634300080f0033", 7 | "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220f27157671d3c5868c24716171f9097885f02c47048143a1215c481954d38a6b164736f6c634300080f0033", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /portal/README.md: -------------------------------------------------------------------------------- 1 | 🌈 _**Portal** is a user-friendly UI portal that provides users with a control interface with low thresholds._ 🌈 2 | --- 3 | 4 | ## 💪🏻 Start 5 | 6 | Required Tools: 7 | - [Node.js](https://nodejs.org/en/download/) >= 14 8 | - [Git](https://git-scm.com/downloads) 9 | 10 | 11 | ```bash 12 | # Project setup 13 | npm install 14 | 15 | # Compiles and hot-reloads for development 16 | npm run serve 17 | 18 | # Compiles and minifies for production 19 | npm run build 20 | ``` 21 | 22 | ## 😃 Contribute 23 | 24 | ### Bug Reports / Feature Requests 25 | If you want to report a bug or request a new feature. Free feel to open a [new issue](https://github.com/FlowShield/FlowShield/pulls). 26 | 27 | ### Pull Requests 28 | 29 | If you want to modify FlowShield-portal, this guideline may be useful for you [CONTRIBUTING](https://github.com/FlowShield/FlowShield/blob/main/portal/CONTRIBUTING.md) 30 | 31 | -------------------------------------------------------------------------------- /portal/src/permission.js: -------------------------------------------------------------------------------- 1 | import router from './router' 2 | import { EventBus } from '@/utils/event-bus' 3 | import store from '@/store' 4 | 5 | const whiteList = ['login', 'home', 'wallet', 'nodes', 'orders', 'resources'] // skip login 6 | 7 | router.beforeEach(async(to, from, next) => { 8 | EventBus.$emit('app.loading', true) 9 | document.title = to?.meta?.title || 'CloudSlit Portal' 10 | 11 | // goto login if needed 12 | try { 13 | await store.dispatch('getUserInfo') 14 | } catch (e) { 15 | if (!whiteList.includes(to.name)) { 16 | EventBus.$emit('app.message', 'Need login', 'warning') 17 | hideLoading() 18 | next({ name: 'login' }) 19 | } 20 | } 21 | 22 | next() 23 | }) 24 | 25 | router.afterEach(_ => { 26 | hideLoading() 27 | }) 28 | 29 | function hideLoading() { 30 | window.setTimeout(() => { 31 | EventBus.$emit('app.loading', false) 32 | }, 100) 33 | } 34 | -------------------------------------------------------------------------------- /ca/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "github.com/flowshield/flowshield/ca/cmd" 6 | "github.com/flowshield/flowshield/ca/initer" 7 | "github.com/flowshield/flowshield/ca/pkg/logger" 8 | "github.com/urfave/cli" 9 | "os" 10 | ) 11 | 12 | func main() { 13 | ctx := context.Background() 14 | 15 | app := cli.NewApp() 16 | app.Name = "capitalizone" 17 | app.Version = "1.0.0" 18 | app.Usage = "capitalizone" 19 | app.Commands = []cli.Command{ 20 | newTlsCmd(ctx), 21 | } 22 | app.Before = initer.Init 23 | err := app.Run(os.Args) 24 | if err != nil { 25 | logger.Named("Init").Errorf(err.Error()) 26 | } 27 | } 28 | 29 | // newTlsCmd Running TLS service 30 | func newTlsCmd(ctx context.Context) cli.Command { 31 | return cli.Command{ 32 | Name: "tls", 33 | Usage: "Running TLS service", 34 | Action: func(c *cli.Context) error { 35 | return cmd.RunTls(ctx) 36 | }, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /portal/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /provider/internal/dao/provider/service/provider.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/provider/internal/dao/provider/dao" 5 | "github.com/flowshield/flowshield/provider/internal/dao/provider/model" 6 | ) 7 | 8 | func ListProvider(param *model.Provider) (model.Providers, error) { 9 | list, err := dao.NewProvider().ListProvider(param) 10 | if err != nil { 11 | return nil, err 12 | } 13 | return list, err 14 | } 15 | 16 | func AddProvider(item *model.Provider) error { 17 | data, err := dao.NewProvider().GetProviderByUuid(item.Uuid) 18 | if err != nil { 19 | return err 20 | } 21 | if data.ID > 0 { 22 | item.ID = data.ID 23 | item.CreatedAt = data.CreatedAt 24 | err = dao.NewProvider().EditProvider(item) 25 | if err != nil { 26 | return err 27 | } 28 | } else { 29 | err = dao.NewProvider().AddProvider(item) 30 | if err != nil { 31 | return err 32 | } 33 | } 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /portal/tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /client/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "github.com/flowshield/flowshield/client/internal" 6 | "github.com/flowshield/flowshield/client/pkg/logger" 7 | "github.com/urfave/cli/v2" 8 | "os" 9 | ) 10 | 11 | var VERSION = "0.0.0" 12 | 13 | func main() { 14 | logger.SetVersion(VERSION) 15 | ctx := logger.NewTagContext(context.Background(), "__main__") 16 | 17 | app := cli.NewApp() 18 | app.Name = "za-sentinel" 19 | app.Version = VERSION 20 | app.Usage = "Security, network acceleration, zero trust network architecture" 21 | app.Flags = []cli.Flag{ 22 | &cli.StringFlag{ 23 | Name: "conf", 24 | Aliases: []string{"c"}, 25 | Usage: "App configuration file(.toml .json .yaml)", 26 | }, 27 | } 28 | app.Action = func(c *cli.Context) error { 29 | return internal.Run(ctx, 30 | internal.SetConfigFile(c.String("conf"))) 31 | } 32 | err := app.Run(os.Args) 33 | if err != nil { 34 | logger.WithContext(ctx).Errorf("%v", err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fullnode/examples/helm/values.yaml: -------------------------------------------------------------------------------- 1 | deployment: 2 | zaportal: 3 | repository: rovast/za-portal 4 | tag: latest 5 | resources: 6 | requests: 7 | cpu: 50m 8 | memory: 50Mi 9 | limits: 10 | cpu: 1 11 | memory: 200Mi 12 | zamanager: 13 | repository: taosheng205054/zamanager 14 | tag: latest 15 | resources: 16 | requests: 17 | cpu: 50m 18 | memory: 50Mi 19 | limits: 20 | cpu: 1 21 | memory: 200Mi 22 | env: 23 | DOMAIN: 'https://dash.flowshield.xyz' 24 | ZTA_REDIS_ADDR: 'redis:6379' 25 | ZTA_MYSQL_HOST: 'mysql' 26 | ZTA_MYSQL_USER: 'root' 27 | ZTA_MYSQL_PASSWORD: 'root' 28 | ZTA_CA_SIGN_URL: 'https://root-ca-tls:8083' 29 | ZTA_CA_AUTH_KEY: '0739a645a7d6601d9d45f6b237c4edeadad904f2fce53625dfdd541ec4fc8134' 30 | 31 | replicas: 3 32 | 33 | ingress: 34 | host: dash.flowshield.xyz 35 | annotations: 36 | 37 | 38 | nodeSelector: {} 39 | tolerations: [] 40 | affinity: {} 41 | -------------------------------------------------------------------------------- /portal/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import vuetify from './plugins/vuetify' 6 | 7 | // clip 8 | import VueClipboard from 'vue-clipboard2' 9 | VueClipboard.config.autoSetContainer = true // add this line 10 | Vue.use(VueClipboard) 11 | 12 | // Auth and permission 13 | import './permission' 14 | 15 | // global css 16 | import './styles/index.scss' 17 | 18 | Vue.config.productionTip = false 19 | 20 | // mount function to Vue prototype, so you can use this.$message component 21 | import { EventBus } from './utils/event-bus' 22 | 23 | Vue.prototype.$message = { 24 | success: (msg = 'Success') => EventBus.$emit('app.message', msg, 'success'), 25 | error: (msg = 'Error') => EventBus.$emit('app.message', msg, 'error'), 26 | warning: (msg = 'Warning') => EventBus.$emit('app.message', msg, 'warning') 27 | } 28 | 29 | new Vue({ 30 | router, 31 | store, 32 | vuetify, 33 | render: h => h(App) 34 | }).$mount('#app') 35 | -------------------------------------------------------------------------------- /fullnode/app/v1/node/model/mmysql/node.go: -------------------------------------------------------------------------------- 1 | package mmysql 2 | 3 | import ( 4 | "database/sql/driver" 5 | "encoding/json" 6 | ) 7 | 8 | type Node struct { 9 | ID uint `gorm:"primarykey"` 10 | CreatedAt int64 `gorm:"autoCreateTime"` 11 | UpdatedAt int64 `gorm:"autoUpdateTime"` 12 | PeerId string `json:"peer_id"` 13 | Addr string `json:"addr"` 14 | Port int `json:"port"` 15 | IP string `json:"ip"` 16 | Loc string `json:"loc"` 17 | Colo string `json:"colo"` 18 | Price uint `json:"price"` 19 | Type string `json:"type"` 20 | } 21 | 22 | func (Node) TableName() string { 23 | return "zta_node" 24 | } 25 | 26 | type MetaData struct { 27 | Ip string `json:"ip"` 28 | Loc string `json:"loc"` 29 | Colo string `json:"colo"` 30 | } 31 | 32 | func (c MetaData) Value() (driver.Value, error) { 33 | b, err := json.Marshal(c) 34 | return string(b), err 35 | } 36 | 37 | func (c *MetaData) Scan(input interface{}) error { 38 | return json.Unmarshal(input.([]byte), c) 39 | } 40 | -------------------------------------------------------------------------------- /ca/pkg/spiffe/idg.go: -------------------------------------------------------------------------------- 1 | package spiffe 2 | 3 | import ( 4 | "github.com/spiffe/go-spiffe/v2/spiffeid" 5 | "strings" 6 | ) 7 | 8 | // IDG Identity 9 | // be like "spiffe://siteid/clusterid/unique_id" 10 | type IDGIdentity struct { 11 | SiteID string `json:"site_id"` 12 | ClusterID string `json:"cluster_id"` 13 | UniqueID string `json:"unique_id"` 14 | } 15 | 16 | func ParseIDGIdentity(s string) (*IDGIdentity, error) { 17 | id, err := spiffeid.FromString(s) 18 | if err != nil { 19 | return nil, err 20 | } 21 | split := strings.Split(strings.Trim(id.Path(), "/"), "/") 22 | var idi IDGIdentity 23 | idi.SiteID = id.TrustDomain().String() 24 | if len(split) > 0 { 25 | idi.ClusterID = split[0] 26 | } 27 | if len(split) > 1 { 28 | idi.UniqueID = split[1] 29 | } 30 | return &idi, nil 31 | } 32 | 33 | func (i IDGIdentity) SpiffeID() spiffeid.ID { 34 | id, _ := spiffeid.New(i.SiteID, i.ClusterID, i.UniqueID) 35 | return id 36 | } 37 | 38 | func (i IDGIdentity) String() string { 39 | return i.SpiffeID().String() 40 | } 41 | -------------------------------------------------------------------------------- /fullnode/app/v1/access/model/mapi/client.go: -------------------------------------------------------------------------------- 1 | package mapi 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/app/base/mapi" 5 | ) 6 | 7 | type ClientList struct { 8 | List []Client `json:"list"` 9 | Paginate mapi.AdminPaginate `json:"paginate"` 10 | } 11 | 12 | type Client struct { 13 | ID uint `gorm:"primarykey"` 14 | CreatedAt int64 `gorm:"autoCreateTime"` 15 | UpdatedAt int64 `gorm:"autoUpdateTime"` 16 | UserUUID string `json:"user_uuid" gorm:"user_uuid"` 17 | Name string `json:"name"` 18 | PeerID string `json:"peer_id"` 19 | UUID string `json:"uuid" gorm:"column:uuid"` 20 | Port int `json:"port"` 21 | Duration uint `json:"duration"` // 使用时间:小时 22 | Price uint `json:"price"` // 金额 23 | ResourceCid string `json:"resource_cid"` 24 | ServerCid string `json:"server_cid"` 25 | ClientCid string `json:"client_cid"` 26 | Status uint `json:"status"` // 0:待支付,1:已支付,待回调,2:已完成 27 | NodeIP string `json:"node_ip"` 28 | } 29 | -------------------------------------------------------------------------------- /fullnode/app/v1/access/model/mparam/resource.go: -------------------------------------------------------------------------------- 1 | package mparam 2 | 3 | import "github.com/flowshield/flowshield/fullnode/app/base/mdb" 4 | 5 | type ResourceList struct { 6 | mdb.Paginate 7 | Name string `json:"name" form:"name"` 8 | Type string `json:"type" form:"type"` 9 | } 10 | 11 | type AddResource struct { 12 | Name string `json:"name" form:"name" binding:"required"` 13 | Type string `json:"type" form:"name" binding:"oneof=cidr dns"` 14 | Host string `json:"host" form:"host" binding:"required"` // api.github.com,192.168.1.1/16 15 | Port string `json:"port" form:"port" binding:"required"` // 80-443;3306;6379 16 | } 17 | 18 | type EditResource struct { 19 | ID uint64 `json:"id" form:"id" binding:"required"` 20 | Name string `json:"name" form:"name" binding:"required"` 21 | Type string `json:"type" form:"name" binding:"oneof=cidr dns"` 22 | Host string `json:"host" form:"host" binding:"required"` // api.github.com,192.168.1.1/16 23 | Port string `json:"port" form:"port" binding:"required"` // 80-443;3306;6379 24 | } 25 | -------------------------------------------------------------------------------- /portal/tests/e2e/plugins/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | // https://docs.cypress.io/guides/guides/plugins-guide.html 3 | 4 | // if you need a custom webpack configuration you can uncomment the following import 5 | // and then use the `file:preprocessor` event 6 | // as explained in the cypress docs 7 | // https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples 8 | 9 | // /* eslint-disable import/no-extraneous-dependencies, global-require */ 10 | // const webpack = require('@cypress/webpack-preprocessor') 11 | 12 | module.exports = (on, config) => { 13 | // on('file:preprocessor', webpack({ 14 | // webpackOptions: require('@vue/cli-service/webpack.config'), 15 | // watchOptions: {} 16 | // })) 17 | 18 | return Object.assign({}, config, { 19 | fixturesFolder: 'tests/e2e/fixtures', 20 | integrationFolder: 'tests/e2e/specs', 21 | screenshotsFolder: 'tests/e2e/screenshots', 22 | videosFolder: 'tests/e2e/videos', 23 | supportFile: 'tests/e2e/support/index.js' 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /provider/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "github.com/urfave/cli/v2" 8 | 9 | "github.com/flowshield/flowshield/provider/internal" 10 | "github.com/flowshield/flowshield/provider/pkg/logger" 11 | ) 12 | 13 | var VERSION = "0.0.0" 14 | 15 | func main() { 16 | logger.SetVersion(VERSION) 17 | ctx := logger.NewTagContext(context.Background(), "__main__") 18 | 19 | app := cli.NewApp() 20 | app.Name = "provider" 21 | app.Version = VERSION 22 | app.Usage = "Security, network acceleration, zero trust network architecture" 23 | app.Flags = []cli.Flag{ 24 | &cli.StringFlag{ 25 | Name: "conf", 26 | Aliases: []string{"c"}, 27 | Usage: "App configuration file(.toml .json .yaml)", 28 | Value: "configs/config.toml", 29 | }, 30 | } 31 | app.Action = func(c *cli.Context) error { 32 | return internal.Run(ctx, 33 | internal.SetConfigFile(c.String("conf"))) 34 | } 35 | err := app.Run(os.Args) 36 | if err != nil { 37 | logger.WithContext(ctx).Errorf("%v", err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ca/initer/logger.go: -------------------------------------------------------------------------------- 1 | package initer 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/ca/pkg/logger/redis_hook" 5 | "log" 6 | 7 | "github.com/flowshield/flowshield/ca/pkg/logger" 8 | "go.uber.org/zap/zapcore" 9 | 10 | "github.com/flowshield/flowshield/ca/core" 11 | ) 12 | 13 | func initLogger(config *core.Config) { 14 | conf := &logger.Conf{ 15 | AppInfo: &logger.ConfigAppData{ 16 | AppVersion: config.Version, 17 | Language: "zh-cn", 18 | }, 19 | Debug: config.Debug, 20 | Caller: true, 21 | } 22 | if config.Debug { 23 | conf.Level = zapcore.DebugLevel 24 | } else { 25 | conf.Level = zapcore.InfoLevel 26 | if config.Log.LogProxy.Host != "" { 27 | conf.HookConfig = &redis_hook.HookConfig{ 28 | Key: config.Log.LogProxy.Key, 29 | Host: config.Log.LogProxy.Host, 30 | Port: config.Log.LogProxy.Port, 31 | } 32 | } 33 | } 34 | if warn := logger.GlobalConfig(*conf); warn != nil { 35 | log.Print("[WARN] logger init error:", warn) 36 | } 37 | 38 | log.Print("[INIT] logger init success.") 39 | } 40 | -------------------------------------------------------------------------------- /fullnode/pkg/middle/oauth2.go: -------------------------------------------------------------------------------- 1 | package middle 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/flowshield/flowshield/fullnode/app/v1/user/model/mmysql" 8 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 9 | "github.com/gin-gonic/contrib/sessions" 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | func Oauth2() gin.HandlerFunc { 14 | return func(ctx *gin.Context) { 15 | session := sessions.Default(ctx) 16 | if user := session.Get("user"); user != nil { 17 | ctx.Set("user", user) 18 | ctx.Next() 19 | } else { 20 | if confer.ConfigEnvGet() == "dev" { 21 | userBytes, _ := json.Marshal(&mmysql.User{ 22 | Email: "nisainan@github.com", 23 | AvatarUrl: "https://avatars.githubusercontent.com/u/25074107?v=4", 24 | UUID: "3933d404-2025-4851-bfe3-1c07c5280c72", 25 | }) 26 | ctx.Set("user", userBytes) 27 | ctx.Next() 28 | } else { 29 | ctx.AbortWithStatus(http.StatusUnauthorized) 30 | } 31 | //ctx.AbortWithStatus(http.StatusUnauthorized) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ca/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth_keys": { 3 | "intermediate": { 4 | "type": "standard", 5 | "key": "52abb3ac91971bb72bce17e7a289cd04476490b19e0d8eb7810dc42d4ac16c41" 6 | }, 7 | "default": { 8 | "type": "standard", 9 | "key": "0739a645a7d6601d9d45f6b237c4edeadad904f2fce53625dfdd541ec4fc8134" 10 | } 11 | }, 12 | "signing": { 13 | "profiles": { 14 | "default": { 15 | "usages": [ 16 | "signing", 17 | "key encipherment", 18 | "server auth", 19 | "client auth" 20 | ], 21 | "expiry": "1440h", 22 | "copy_extensions": true, 23 | "auth_key": "default" 24 | }, 25 | "intermediate": { 26 | "usages": [ 27 | "digital signature", 28 | "cert sign", 29 | "crl sign" 30 | ], 31 | "expiry": "17520h", 32 | "copy_extensions": true, 33 | "auth_key": "intermediate", 34 | "ca_constraint": { 35 | "is_ca": true 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /fullnode/server/http.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 8 | "github.com/flowshield/flowshield/fullnode/pkg/gin" 9 | "github.com/flowshield/flowshield/fullnode/pkg/middle" 10 | "github.com/flowshield/flowshield/fullnode/route" 11 | 12 | swaggerFiles "github.com/swaggo/files" 13 | ginSwagger "github.com/swaggo/gin-swagger" 14 | ) 15 | 16 | func RunHTTP() { 17 | engine := gin.NewGin() 18 | //engine.Use(middle.RequestID()) 19 | // 仅针对开发环境生效的组件 20 | //if confer.ConfigEnvIsDev() { 21 | // 跨域中间件 22 | engine.Use(middle.CorsV2()) 23 | // swagger 24 | engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) 25 | //} 26 | engine.Use(middle.Session("zta", &confer.GlobalConfig().Redis)) 27 | route.Home(engine) 28 | route.Api(engine) 29 | route.NotFound(engine) 30 | httpPort := confer.ConfigAppGetInt("port", 80) 31 | portStr := ":" + strconv.Itoa(httpPort) 32 | fmt.Println("start", httpPort) 33 | gin.ListenHTTP(portStr, engine, 10) 34 | } 35 | -------------------------------------------------------------------------------- /contract/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | require("@nomiclabs/hardhat-waffle"); 3 | require("@openzeppelin/hardhat-upgrades"); 4 | // Go to https://infura.io/ and create a new project 5 | // Replace this with your Infura project ID 6 | const INFURA_PROJECT_ID = "811238fc53164a35a96f841a7a89bea5"; 7 | 8 | /** 9 | * @type import('hardhat/config').HardhatUserConfig 10 | */ 11 | module.exports = { 12 | solidity: "0.8.15", 13 | networks: { 14 | ropsten: { 15 | url: `https://ropsten.infura.io/v3/${INFURA_PROJECT_ID}`, 16 | accounts: [process.env.PRIVATE_KEY] 17 | }, 18 | 'godwoken-testnet': { 19 | url: `https://godwoken-testnet-v1.ckbapp.dev`, 20 | accounts: [process.env.PRIVATE_KEY] 21 | }, 22 | matic: { 23 | url: "https://rpc-mumbai.maticvigil.com", 24 | accounts: [process.env.PRIVATE_KEY] 25 | } 26 | }, 27 | etherscan: { 28 | apiKey: process.env.POLYGONSCAN_API_KEY 29 | }, 30 | defaultNetwork: "matic", 31 | }; -------------------------------------------------------------------------------- /ca/pkg/keyprovider/xkey_provider_test.go: -------------------------------------------------------------------------------- 1 | package keyprovider 2 | 3 | import ( 4 | "fmt" 5 | "github.com/flowshield/flowshield/ca/pkg/keygen" 6 | "github.com/flowshield/flowshield/ca/pkg/spiffe" 7 | "testing" 8 | ) 9 | 10 | var ( 11 | testID = &spiffe.IDGIdentity{ 12 | SiteID: "test_site", 13 | ClusterID: "test_cluster", 14 | UniqueID: "unique_id", 15 | } 16 | ) 17 | 18 | func TestXKeyProvider_Generate(t *testing.T) { 19 | kp, _ := NewXKeyProvider(&spiffe.IDGIdentity{}) 20 | err := kp.Generate(string(keygen.EcdsaSigAlg), 0) 21 | if err != nil { 22 | t.Error(err) 23 | } 24 | err = kp.Generate(string(keygen.RsaSigAlg), 0) 25 | if err != nil { 26 | t.Error(err) 27 | } 28 | } 29 | 30 | func TestXKeyProvider_CertificateRequest(t *testing.T) { 31 | kp, _ := NewXKeyProvider(testID) 32 | err := kp.Generate(string(keygen.EcdsaSigAlg), 0) 33 | if err != nil { 34 | t.Error(err) 35 | } 36 | csr, err := kp.CertificateRequest(nil) 37 | if err != nil { 38 | t.Error(err) 39 | } 40 | fmt.Println("----------------------------\n", 41 | string(csr)) 42 | } 43 | -------------------------------------------------------------------------------- /deploy/fullnode/docker-compose/ca_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth_keys": { 3 | "intermediate": { 4 | "type": "standard", 5 | "key": "52abb3ac91971bb72bce17e7a289cd04476490b19e0d8eb7810dc42d4ac16c41" 6 | }, 7 | "default": { 8 | "type": "standard", 9 | "key": "0739a645a7d6601d9d45f6b237c4edeadad904f2fce53625dfdd541ec4fc8134" 10 | } 11 | }, 12 | "signing": { 13 | "profiles": { 14 | "default": { 15 | "usages": [ 16 | "signing", 17 | "key encipherment", 18 | "server auth", 19 | "client auth" 20 | ], 21 | "expiry": "1440h", 22 | "copy_extensions": true, 23 | "auth_key": "default" 24 | }, 25 | "intermediate": { 26 | "usages": [ 27 | "digital signature", 28 | "cert sign", 29 | "crl sign" 30 | ], 31 | "expiry": "17520h", 32 | "copy_extensions": true, 33 | "auth_key": "intermediate", 34 | "ca_constraint": { 35 | "is_ca": true 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /fullnode/pkg/p2p/server.go: -------------------------------------------------------------------------------- 1 | package p2p 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 5 | "github.com/flowshield/flowshield/fullnode/pkg/logger" 6 | ) 7 | 8 | var pubSubObj *PubSub 9 | 10 | func InitP2P(cfg *confer.P2P) (err error) { 11 | logger.Infof("Starting P2P...") 12 | p2phost := NewP2P(cfg.ServiceDiscoveryID) 13 | logger.Infof("Completed P2P Setup") 14 | // Connect to peers with the chosen discovery method 15 | switch cfg.ServiceDiscoveryMode { 16 | case "announce": 17 | p2phost.AnnounceConnect() 18 | case "advertise": 19 | p2phost.AdvertiseConnect() 20 | default: 21 | p2phost.AdvertiseConnect() 22 | } 23 | logger.Infof("Connected to Service Peers") 24 | // Join the chat room 25 | pubSubObj, err = JoinPubSub(p2phost, "server_provider", cfg.ServiceMetadataTopic) 26 | if err != nil { 27 | logger.Errorf(nil, "Join PubSub Error: %v", err) 28 | return err 29 | } 30 | logger.Infof("Successfully joined [%s] P2P channel.", cfg.ServiceMetadataTopic) 31 | return 32 | } 33 | 34 | func GetPubSub() *PubSub { 35 | return pubSubObj 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 GITSRC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /fullnode/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | _ "github.com/flowshield/flowshield/fullnode/docs" 7 | "github.com/flowshield/flowshield/fullnode/server" 8 | "github.com/urfave/cli" 9 | _ "go.uber.org/automaxprocs" 10 | ) 11 | 12 | // @title FullNode API 13 | // @version 1.0.0 14 | // @description This is FullNode api list. 15 | // @host 127.0.0.1:80 16 | // @BasePath /api/v1 17 | func main() { 18 | app := cli.NewApp() 19 | app.Name = "FullNode" 20 | app.Author = "TS" 21 | app.Flags = []cli.Flag{ 22 | cli.StringFlag{ 23 | Name: "server", 24 | Value: "http", 25 | Usage: "run server type: http", 26 | }, 27 | cli.StringFlag{ 28 | Name: "c", 29 | Value: "config.yaml", 30 | Usage: "config file url", 31 | }, 32 | } 33 | app.Before = server.InitService 34 | app.Action = func(c *cli.Context) error { 35 | println("RunHttp Server.") 36 | serverType := c.String("server") 37 | switch serverType { 38 | case "http": 39 | server.RunHTTP() 40 | default: 41 | server.RunHTTP() 42 | } 43 | return nil 44 | } 45 | err := app.Run(os.Args) 46 | if err != nil { 47 | panic("app run error:" + err.Error()) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /verifier/app/base/mdb/paginate.go: -------------------------------------------------------------------------------- 1 | package mdb 2 | 3 | type Paginate struct { 4 | Page int `json:"page" form:"page,default=1"` // 分页号 5 | LimitNum int `json:"limit_num" form:"limit_num,default=10"` // 每页限制数量 6 | Offset int // 计算获取offset 7 | } 8 | 9 | func (p *Paginate) Init() { 10 | if p.LimitNum == 0 { 11 | p.LimitNum = 10 // 默认一页10条 12 | } 13 | if p.Page == 0 { 14 | p.Page = 1 15 | } 16 | p.Offset = p.getOffset() 17 | } 18 | 19 | func (p *Paginate) getOffset() int { 20 | offset := (p.Page - 1) * p.LimitNum 21 | if offset < 0 { 22 | offset = 0 23 | } 24 | return offset 25 | } 26 | 27 | func (p *Paginate) GetOffset() int { 28 | offset := (p.Page - 1) * p.LimitNum 29 | if offset < 0 { 30 | offset = 0 31 | } 32 | p.Offset = offset 33 | return offset 34 | } 35 | 36 | func (p *Paginate) GetPageNum(limitNum int, defaultNum int) int { 37 | if limitNum > 20 { 38 | return 10 39 | } else if limitNum <= 0 { 40 | return defaultNum 41 | } else { 42 | return limitNum 43 | } 44 | } 45 | 46 | func (p *Paginate) DealOffset() { 47 | if p.Page == 0 { 48 | p.Page = 1 49 | } 50 | p.LimitNum = p.GetPageNum(p.LimitNum, 10) 51 | p.GetOffset() 52 | return 53 | } 54 | -------------------------------------------------------------------------------- /fullnode/route/route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/app/base/controller" 5 | v1 "github.com/flowshield/flowshield/fullnode/app/v1/controlplane/controller" 6 | "github.com/flowshield/flowshield/fullnode/pconst" 7 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 8 | "github.com/flowshield/flowshield/fullnode/route/access" 9 | "github.com/flowshield/flowshield/fullnode/route/controlplane" 10 | "github.com/flowshield/flowshield/fullnode/route/node" 11 | "github.com/flowshield/flowshield/fullnode/route/user" 12 | 13 | "github.com/gin-gonic/gin" 14 | ) 15 | 16 | // Home 主页 17 | func Home(engine *gin.Engine) { 18 | engine.GET("", controller.Welcome) 19 | } 20 | 21 | func Api(engine *gin.Engine) { 22 | engine.GET("/a/:hash", v1.MachineOauth) 23 | prefix := confer.ConfigAppGetString("UrlPrefix", "") 24 | RouteV1 := engine.Group(prefix + pconst.APIAPIV1URL) 25 | { 26 | access.APIAccess(RouteV1) 27 | node.APINode(RouteV1) 28 | controlplane.APIControlPlane(RouteV1) 29 | user.APIUser(RouteV1) 30 | } 31 | } 32 | 33 | func NotFound(r *gin.Engine) { 34 | r.NoRoute(func(c *gin.Context) { 35 | c.String(404, "404 Not Found") 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /provider/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: start build 2 | 3 | SERVER_BIN = ./bin/provider 4 | GIT_COUNT = $(shell git rev-list --all --count) 5 | GIT_HASH = $(shell git rev-parse --short HEAD) 6 | RELEASE_TAG = $(GIT_COUNT).$(GIT_HASH) 7 | 8 | GOPROXY=https://goproxy.cn,direct 9 | 10 | CFLAGS = -ldflags "-w -s -X main.VERSION=$(RELEASE_TAG)" -o $(SERVER_BIN) 11 | 12 | all: release 13 | 14 | test: 15 | @go test -v $(shell go list ./...) 16 | 17 | build: 18 | if [ ! -d "./bin/" ]; then \ 19 | mkdir bin; \ 20 | fi 21 | GOPROXY=$(GOPROXY) CGO_ENABLED=0 go build $(CFLAGS) ./cmd 22 | 23 | release: 24 | if [ ! -d "./bin/" ]; then \ 25 | mkdir bin; \ 26 | fi 27 | GOPROXY=$(GOPROXY) CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(CFLAGS) ./cmd 28 | 29 | ################################################################################ 30 | # Target: format # 31 | ################################################################################ 32 | .PHONY: format 33 | format: modtidy 34 | gofumpt -l -w . && goimports -local github.com/flowshield/ -w $(shell find ./ -type f -name '*.go' -not -path "./test") 35 | 36 | .PHONY: modtidy 37 | modtidy: 38 | go mod tidy -------------------------------------------------------------------------------- /portal/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import { fetchUser } from '@/api' 4 | 5 | Vue.use(Vuex) 6 | 7 | const store = new Vuex.Store({ 8 | state: { 9 | user: { 10 | avatar: '', 11 | email: '', 12 | uuid: '', 13 | master: '' 14 | }, 15 | ceramic: { 16 | uuid: '', 17 | address: '' 18 | } 19 | }, getters: {}, mutations: { 20 | SET_USER(state, info) { 21 | state.user.avatar = info.avatar_url 22 | state.user.email = info.email 23 | state.user.master = info.master 24 | state.user.uuid = info.uuid 25 | }, SET_CERAMIC(state, info) { 26 | state.ceramic.uuid = info.uuid 27 | state.ceramic.address = info.address 28 | } 29 | }, actions: { 30 | getUserInfo({ commit, state }) { 31 | return new Promise((resolve, reject) => { 32 | if (state.user.email) { 33 | resolve() 34 | return 35 | } 36 | 37 | fetchUser().then(res => { 38 | commit('SET_USER', res.data) 39 | resolve() 40 | }).catch(error => { 41 | reject(error) 42 | }) 43 | }) 44 | } 45 | }, modules: {} 46 | }) 47 | 48 | export default store 49 | -------------------------------------------------------------------------------- /fullnode/app/base/mdb/paginate.go: -------------------------------------------------------------------------------- 1 | package mdb 2 | 3 | type Paginate struct { 4 | Page int `json:"page" form:"page,default=1"` // page number 5 | LimitNum int `json:"limit_num" form:"limit_num,default=10"` // limit number of page 6 | Offset int // Calculate and obtain offset 7 | } 8 | 9 | func (p *Paginate) Init() { 10 | if p.LimitNum == 0 { 11 | p.LimitNum = 10 // Default is 10 items per page 12 | } 13 | if p.Page == 0 { 14 | p.Page = 1 15 | } 16 | p.Offset = p.getOffset() 17 | } 18 | 19 | func (p *Paginate) getOffset() int { 20 | offset := (p.Page - 1) * p.LimitNum 21 | if offset < 0 { 22 | offset = 0 23 | } 24 | return offset 25 | } 26 | 27 | func (p *Paginate) GetOffset() int { 28 | offset := (p.Page - 1) * p.LimitNum 29 | if offset < 0 { 30 | offset = 0 31 | } 32 | p.Offset = offset 33 | return offset 34 | } 35 | 36 | func (p *Paginate) GetPageNum(limitNum int, defaultNum int) int { 37 | if limitNum > 20 { 38 | return 10 39 | } else if limitNum <= 0 { 40 | return defaultNum 41 | } else { 42 | return limitNum 43 | } 44 | } 45 | 46 | func (p *Paginate) DealOffset() { 47 | if p.Page == 0 { 48 | p.Page = 1 49 | } 50 | p.LimitNum = p.GetPageNum(p.LimitNum, 10) 51 | p.GetOffset() 52 | return 53 | } 54 | -------------------------------------------------------------------------------- /portal/src/utils/request-helper.js: -------------------------------------------------------------------------------- 1 | import { EventBus } from '@/utils/event-bus' 2 | 3 | /** 4 | * @param service AxiosInstance 5 | * @param flag String 6 | */ 7 | export function requestInterceptors(service, flag = '') { 8 | service.interceptors.request.use( 9 | config => { 10 | // if (store.getters.token) { 11 | // config.headers['Authorization'] = 'Bear ' + store.getters.token 12 | // } 13 | return config 14 | }, 15 | error => { 16 | // do something with request error 17 | console.log(error) // for debug 18 | return Promise.reject(error) 19 | } 20 | ) 21 | 22 | service.interceptors.response.use( 23 | response => { 24 | const res = response.data 25 | 26 | if (res.code === 1001) { 27 | return res 28 | } 29 | 30 | return Promise.reject(response) 31 | }, 32 | error => { 33 | const statusCode = error.response.status 34 | 35 | if (statusCode === 401 && ['/login', '/'].includes(window.location.pathname)) { // ignore error message 36 | return Promise.reject(error) 37 | } 38 | 39 | EventBus.$emit('app.message', `[${statusCode}] ${error.message}`, 'error') 40 | return Promise.reject(error) 41 | } 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /ca/pkg/pkiutil/dual_use.go: -------------------------------------------------------------------------------- 1 | // Copyright Istio Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pkiutil 16 | 17 | import ( 18 | "fmt" 19 | "strings" 20 | ) 21 | 22 | // DualUseCommonName extracts a valid CommonName from a comma-delimited host string 23 | // for dual-use certificates. 24 | func DualUseCommonName(host string) (string, error) { 25 | // cn uses one hostname, drop the rest 26 | first := strings.SplitN(host, ",", 2)[0] 27 | 28 | // cn max length is 64 (ub-common-name @ https://tools.ietf.org/html/rfc5280) 29 | if l := len(first); l > 64 { 30 | return "", fmt.Errorf("certificate CN upper bound exceeded (%v>64): %s", l, first) 31 | } 32 | 33 | return first, nil 34 | } 35 | -------------------------------------------------------------------------------- /client/configs/config.toml: -------------------------------------------------------------------------------- 1 | # mode(debug,test,release) 2 | RunMode = "release" 3 | 4 | # Whether to print configuration parameters at startup 5 | PrintConfig = true 6 | 7 | # Information about themselves 8 | [App] 9 | # Listening address 10 | LocalAddr = "0.0.0.0" 11 | # Listening port 12 | LocalPort = 3091 13 | # Control end address, "Used to obtain configuration or rule information" 14 | ControlHost = "https://dash.flowshield.xyz" 15 | 16 | # w3s token 17 | [Web3.W3s] 18 | Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDU4MUJkZEVGNTA3MDlmZjIzQzEwN0Q5YUU2NEVlMjc5M0IyMzk3NWMiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2NTY2NDc2MDM2MjUsIm5hbWUiOiJjbG91ZHNsaXQifQ.7iUZuCDn1SNn7CxuR_kdAWf9_PfpuJlqPmy7ZdB2x9U" 19 | # Request timeout (unit/second) 20 | Timeout = 10 21 | # Request failed retries 22 | RetryCount = 100 23 | 24 | [Log] 25 | # level(1:fatal,2:error,3:warn,4:info,5:debug,6:trace) 26 | Level = 4 27 | # text、json 28 | Format = "text" 29 | # stdout、stderr、file 30 | Output = "stdout" 31 | OutputFile = "data/logger.log" 32 | EnableHook = false 33 | HookLevels = ["info", "warn", "error"] 34 | # gorm、redis 35 | Hook = "redis" 36 | HookMaxThread = 1 37 | HookMaxBuffer = 512 38 | 39 | [LogRedisHook] 40 | Addr = "127.0.0.1:6379" 41 | Key = "log_key" 42 | 43 | -------------------------------------------------------------------------------- /client/pkg/logger/hook/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | "github.com/flowshield/flowshield/client/pkg/util/json" 6 | 7 | "github.com/go-redis/redis" 8 | "github.com/sirupsen/logrus" 9 | ) 10 | 11 | type Config struct { 12 | Addr string 13 | Password string 14 | Key string 15 | } 16 | 17 | func New(c *Config) *Hook { 18 | redisdb := redis.NewClient(&redis.Options{ 19 | Addr: c.Addr, // use default Addr 20 | Password: c.Password, // no password set 21 | DB: 0, // use default DB 22 | }) 23 | 24 | _, err := redisdb.Ping().Result() 25 | if err != nil { 26 | fmt.Println("error creating message for REDIS:", err) 27 | panic(err) 28 | } 29 | return &Hook{ 30 | cli: redisdb, 31 | key: c.Key, 32 | } 33 | } 34 | 35 | type Hook struct { 36 | cli *redis.Client 37 | key string 38 | } 39 | 40 | func (h *Hook) Exec(entry *logrus.Entry) error { 41 | fields := make(map[string]interface{}) 42 | for k, v := range entry.Data { 43 | fields[k] = v 44 | } 45 | fields["level"] = entry.Level.String() 46 | fields["message"] = entry.Message 47 | b, _ := json.Marshal(fields) 48 | return h.cli.RPush(h.key, string(b)).Err() 49 | } 50 | 51 | func (h *Hook) Close() error { 52 | return h.cli.Close() 53 | } 54 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # FlowShield Client 2 | 3 | This is the FlowShield client program. 4 | 5 | You need to communicate with the whole node through this program to obtain the configuration and zero trust edge calculation rules. Communicate with network providers through this program. 6 | 7 | ## How does it work? 8 | 9 | ### Scene Introduction 10 | image 11 | 12 | ## Getting Started 13 | 14 | ### Configuration 15 | 16 | In the configs directory, the user stores the project configuration file with the file name: config.toml, which can be modified according to your own needs 17 | 18 | By default, you do not need to modify the configuration file, just refer to QuickStart. 19 | 20 | ### Quickstart 21 | ```shell 22 | $ make 23 | $ ./bin/client 24 | ``` 25 | 26 | ## License 27 | FlowShield-client uses Apache 2.0 license. See [license](LICENSE) directory for details 28 | 29 | ## Disclaimers 30 | When you use this software, you have agreed and declared that the author, maintainer and contributor of this software are not responsible for any risks, costs or problems you encounter. If you find a software defect or bug, please submit a patch to help improve! 31 | -------------------------------------------------------------------------------- /provider/pkg/logger/hook/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/flowshield/flowshield/provider/pkg/util/json" 7 | 8 | "github.com/go-redis/redis" 9 | "github.com/sirupsen/logrus" 10 | ) 11 | 12 | type Config struct { 13 | Addr string 14 | Password string 15 | Key string 16 | } 17 | 18 | func New(c *Config) *Hook { 19 | redisdb := redis.NewClient(&redis.Options{ 20 | Addr: c.Addr, // use default Addr 21 | Password: c.Password, // no password set 22 | DB: 0, // use default DB 23 | }) 24 | 25 | _, err := redisdb.Ping().Result() 26 | if err != nil { 27 | fmt.Println("error creating message for REDIS:", err) 28 | panic(err) 29 | } 30 | return &Hook{ 31 | cli: redisdb, 32 | key: c.Key, 33 | } 34 | } 35 | 36 | type Hook struct { 37 | cli *redis.Client 38 | key string 39 | } 40 | 41 | func (h *Hook) Exec(entry *logrus.Entry) error { 42 | fields := make(map[string]interface{}) 43 | for k, v := range entry.Data { 44 | fields[k] = v 45 | } 46 | fields["level"] = entry.Level.String() 47 | fields["message"] = entry.Message 48 | b, _ := json.Marshal(fields) 49 | return h.cli.RPush(h.key, string(b)).Err() 50 | } 51 | 52 | func (h *Hook) Close() error { 53 | return h.cli.Close() 54 | } 55 | -------------------------------------------------------------------------------- /ca/pkg/signature/signer.go: -------------------------------------------------------------------------------- 1 | package signature 2 | 3 | import ( 4 | "crypto" 5 | "crypto/ecdsa" 6 | "crypto/rsa" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | // Signer ... 12 | type Signer struct { 13 | priv crypto.PrivateKey 14 | } 15 | 16 | // NewSigner ... 17 | func NewSigner(priv crypto.PrivateKey) *Signer { 18 | return &Signer{priv: priv} 19 | } 20 | 21 | // Sign 22 | func (s *Signer) Sign(text []byte) (sign string, err error) { 23 | switch priv := s.priv.(type) { 24 | case *ecdsa.PrivateKey: 25 | sign, err = EcdsaSign(priv, text) 26 | return 27 | case *rsa.PrivateKey: 28 | // Todo supports RSA 29 | return "", errors.New("algo not supported") 30 | default: 31 | return "", errors.New("algo not supported") 32 | } 33 | } 34 | 35 | // Verifier ... 36 | type Verifier struct { 37 | pub crypto.PublicKey 38 | } 39 | 40 | // NewVerifier ... 41 | func NewVerifier(pub crypto.PublicKey) *Verifier { 42 | return &Verifier{pub: pub} 43 | } 44 | 45 | // Verify Verify signature 46 | func (v *Verifier) Verify(text []byte, sign string) (bool, error) { 47 | switch pub := v.pub.(type) { 48 | case *ecdsa.PublicKey: 49 | return EcdsaVerify(text, sign, pub) 50 | case *rsa.PublicKey: 51 | // Todo supports RSA 52 | default: 53 | } 54 | return false, errors.New("algo not supported") 55 | } 56 | -------------------------------------------------------------------------------- /provider/internal/dao/provider/model/provider.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import "github.com/flowshield/flowshield/provider/internal/schema" 4 | 5 | type Providers []*Provider 6 | 7 | type Provider struct { 8 | ID uint `gorm:"primarykey" json:"id"` 9 | CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"` 10 | UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at"` 11 | ExpiredAt int64 `gorm:"autoExpiredTime" json:"expired_at"` 12 | Uuid string `gorm:"uuid" json:"uuid"` 13 | Wallet string `gorm:"wallet" json:"wallet"` 14 | ServerCid string `gorm:"server_cid" json:"server_cid"` 15 | Port int `gorm:"port" json:"port"` 16 | } 17 | 18 | func (Provider) TableName() string { 19 | return "pr_provider" 20 | } 21 | 22 | func (a *Provider) ToNodeOrder() *schema.NodeOrder { 23 | result := &schema.NodeOrder{ 24 | Uuid: a.Uuid, 25 | Wallet: a.Wallet, 26 | ServerCid: a.ServerCid, 27 | Port: a.Port, 28 | } 29 | return result 30 | } 31 | 32 | func OrderToProvider(order *schema.NodeOrder, pc *schema.ProviderConfig) *Provider { 33 | result := &Provider{ 34 | Uuid: order.Uuid, 35 | Wallet: order.Wallet, 36 | ServerCid: order.ServerCid, 37 | Port: order.Port, 38 | ExpiredAt: pc.CertConfig.NotAfter.Unix(), 39 | } 40 | return result 41 | } 42 | -------------------------------------------------------------------------------- /fullnode/config.yaml: -------------------------------------------------------------------------------- 1 | #APP ENV 2 | app: 3 | env: "release" # dev,release 4 | sysname: "FlowShield" 5 | port: 8080 6 | domain: DOMAIN 7 | 8 | #Mysql 9 | mysql: 10 | dbname: "zta" 11 | prefix: "zta_" 12 | pool: 13 | pool-min-cap: 10 14 | pool-ex-cap: 5 15 | pool-max-cap: 40 16 | pool-idle-timeout: 3600 17 | pool-wait-count: 1000 18 | pool-wai-timeout: 30 19 | write: 20 | host: "CS_MYSQL_HOST" 21 | port: 23306 22 | user: "CS_MYSQL_USER" 23 | password: "CS_MYSQL_PASSWORD" 24 | 25 | #Redis 26 | redis: 27 | addr: "CS_REDIS_ADDR" 28 | 29 | #CA 30 | ca: 31 | sign-url: "CS_CA_SIGN_URL" 32 | auth-key: "CS_CA_AUTH_KEY" 33 | 34 | oauth2: 35 | client-id: "CS_OAUTH2_CLIENT_ID" 36 | client-secret: "CS_OAUTH2_CLIENT_SECRET" 37 | 38 | p2p: 39 | enable: true 40 | # account: "CS_ACCOUNT" 41 | service-discovery-id: "CS_P2P_SERVICE_DISCOVERY_ID" 42 | service-discovery-mode: "advertise" # advertise or announce 43 | service-metadata-topic: "CS_P2P_SERVICE_METADATA_TOPIC" # advertise or announce 44 | 45 | web3: 46 | register: "CS_WEB3_REGIST" 47 | private-key: "CS_PRIVATE_KEY" 48 | contract: 49 | token: "CS_CONTRACT_TOKEN" 50 | w3s: 51 | token: "CS_W3S_TOKEN" 52 | timeout: 10 53 | retry-count: 100 54 | eth: 55 | url: "CS_ETH_URL" 56 | -------------------------------------------------------------------------------- /ca/pkg/logger/example/single_test.go: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/ca/pkg/logger" 5 | "github.com/flowshield/flowshield/ca/pkg/logger/redis_hook" 6 | "go.uber.org/zap/zapcore" 7 | "log" 8 | ) 9 | 10 | var ( 11 | EnvEnableRedisOutput bool // Simulated environment variables 12 | EnvDebug bool 13 | ) 14 | 15 | func init() { 16 | EnvEnableRedisOutput = true 17 | EnvDebug = true 18 | initLogger() 19 | } 20 | 21 | func initLogger() { 22 | conf := &logger.Conf{ 23 | Level: zapcore.DebugLevel, // Output log level 24 | Caller: true, //Whether to open record calling folder + number of lines + function name 25 | Debug: true, // Enable debug 26 | // All logs output to redis are above info level 27 | AppInfo: &logger.ConfigAppData{ 28 | AppVersion: "1.0", 29 | Language: "zh-cn", 30 | }, 31 | } 32 | if !EnvDebug || EnvEnableRedisOutput { 33 | // In case of production environment 34 | conf.Level = zapcore.InfoLevel 35 | conf.HookConfig = &redis_hook.HookConfig{ 36 | Key: "log_key", 37 | Host: "redis.msp", 38 | Port: 6380, 39 | } 40 | } 41 | err := logger.GlobalConfig(*conf) 42 | if err != nil { 43 | log.Print("[ERR] Logger init error: ", err) 44 | } 45 | logger.Infof("info test: %v", "data") 46 | } 47 | -------------------------------------------------------------------------------- /fullnode/pkg/confer/config_app.go: -------------------------------------------------------------------------------- 1 | package confer 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func ConfigAppGetString(key string, defaultConfig string) string { 8 | config := ConfigAppGet(key) 9 | if config == nil { 10 | return defaultConfig 11 | } else { 12 | configStr := config.(string) 13 | if len(strings.TrimSpace(configStr)) == 0 { 14 | configStr = defaultConfig 15 | } 16 | return configStr 17 | } 18 | } 19 | 20 | func ConfigAppGetInt(key string, defaultConfig int) int { 21 | config := ConfigAppGet(key) 22 | if config == nil { 23 | return defaultConfig 24 | } else { 25 | configInt := config.(int) 26 | if configInt == 0 { 27 | configInt = defaultConfig 28 | } 29 | return configInt 30 | } 31 | } 32 | 33 | func ConfigAppGet(key string) interface{} { 34 | globalConfig.RLock() 35 | defer globalConfig.RUnlock() 36 | //将配置文件中的app字段转为map 37 | config, exists := globalConfig.App[key] 38 | if !exists { 39 | return nil 40 | } 41 | return config 42 | } 43 | 44 | func ConfigEnvGet() string { 45 | strEnv := ConfigAppGet("env") 46 | return strEnv.(string) 47 | } 48 | 49 | func ConfigEnvIsDev() bool { 50 | env := ConfigEnvGet() 51 | if env == "dev" { 52 | return true 53 | } 54 | return false 55 | } 56 | 57 | func ConfigEnvIsBeta() bool { 58 | return ConfigEnvGet() == "beta" 59 | } 60 | -------------------------------------------------------------------------------- /fullnode/config_nervos.yaml: -------------------------------------------------------------------------------- 1 | #APP ENV 2 | app: 3 | env: "release" # dev,release 4 | sysname: "FlowShield" 5 | port: 8080 6 | domain: DOMAIN 7 | 8 | #Mysql 9 | mysql: 10 | dbname: "zta" 11 | prefix: "zta_" 12 | pool: 13 | pool-min-cap: 10 14 | pool-ex-cap: 5 15 | pool-max-cap: 40 16 | pool-idle-timeout: 3600 17 | pool-wait-count: 1000 18 | pool-wai-timeout: 30 19 | write: 20 | host: "CS_MYSQL_HOST" 21 | port: 23306 22 | user: "CS_MYSQL_USER" 23 | password: "CS_MYSQL_PASSWORD" 24 | 25 | #Redis 26 | redis: 27 | addr: "CS_REDIS_ADDR" 28 | 29 | #CA 30 | ca: 31 | sign-url: "CS_CA_SIGN_URL" 32 | auth-key: "CS_CA_AUTH_KEY" 33 | 34 | oauth2: 35 | client-id: "CS_OAUTH2_CLIENT_ID" 36 | client-secret: "CS_OAUTH2_CLIENT_SECRET" 37 | 38 | p2p: 39 | enable: true 40 | # account: "CS_ACCOUNT" 41 | service-discovery-id: "flowshield/provider" 42 | service-discovery-mode: "advertise" # advertise or announce 43 | service-metadata-topic: "flowshield_provider_metadata" # advertise or announce 44 | 45 | web3: 46 | register: "CS_WEB3_REGIST" 47 | private-key: "CS_PRIVATE_KEY" 48 | contract: 49 | token: "CS_CONTRACT_TOKEN" 50 | w3s: 51 | token: "CS_W3S_TOKEN" 52 | timeout: 10 53 | retry-count: 100 54 | eth: 55 | url: "https://godwoken-testnet-v1.ckbapp.dev" 56 | projectid: "" 57 | -------------------------------------------------------------------------------- /portal/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | Vue.use(VueRouter) 5 | 6 | const routes = [ 7 | { 8 | path: '/', 9 | name: 'home', 10 | component: () => import('@/views/HomeView') 11 | }, 12 | { 13 | path: '/login', 14 | name: 'login', 15 | component: () => import('@/views/login') 16 | }, 17 | { 18 | path: '/clients', 19 | name: 'clients', 20 | component: () => import('@/views/clients') 21 | }, 22 | { 23 | path: '/servers', 24 | name: 'servers', 25 | component: () => import('@/views/servers') 26 | }, 27 | { 28 | path: '/resources', 29 | name: 'resources', 30 | component: () => import('@/views/resources') 31 | }, 32 | { 33 | path: '/relay', 34 | name: 'relay', 35 | component: () => import('@/views/relay') 36 | }, 37 | { 38 | path: '/nodes', 39 | name: 'nodes', 40 | component: () => import('@/views/nodes') 41 | }, 42 | { 43 | path: '/orders', 44 | name: 'orders', 45 | component: () => import('@/views/orders') 46 | }, 47 | { 48 | path: '/wallet', 49 | name: 'wallet', 50 | component: () => import('@/views/wallet') 51 | } 52 | ] 53 | 54 | const router = new VueRouter({ 55 | mode: 'history', 56 | base: process.env.BASE_URL, 57 | routes 58 | }) 59 | 60 | export default router 61 | -------------------------------------------------------------------------------- /fullnode/config_eth.yaml: -------------------------------------------------------------------------------- 1 | #APP ENV 2 | app: 3 | env: "release" # dev,release 4 | sysname: "FlowShield" 5 | port: 8080 6 | domain: DOMAIN 7 | 8 | #Mysql 9 | mysql: 10 | dbname: "zta" 11 | prefix: "zta_" 12 | pool: 13 | pool-min-cap: 10 14 | pool-ex-cap: 5 15 | pool-max-cap: 40 16 | pool-idle-timeout: 3600 17 | pool-wait-count: 1000 18 | pool-wai-timeout: 30 19 | write: 20 | host: "CS_MYSQL_HOST" 21 | port: 23306 22 | user: "CS_MYSQL_USER" 23 | password: "CS_MYSQL_PASSWORD" 24 | 25 | #Redis 26 | redis: 27 | addr: "CS_REDIS_ADDR" 28 | 29 | #CA 30 | ca: 31 | sign-url: "CS_CA_SIGN_URL" 32 | auth-key: "CS_CA_AUTH_KEY" 33 | 34 | oauth2: 35 | client-id: "CS_OAUTH2_CLIENT_ID" 36 | client-secret: "CS_OAUTH2_CLIENT_SECRET" 37 | 38 | p2p: 39 | enable: true 40 | # account: "CS_ACCOUNT" 41 | service-discovery-id: "flowshield/provider" 42 | service-discovery-mode: "advertise" # advertise or announce 43 | service-metadata-topic: "flowshield_provider_metadata" # advertise or announce 44 | 45 | web3: 46 | register: "CS_WEB3_REGIST" 47 | private-key: "CS_PRIVATE_KEY" 48 | contract: 49 | token: "CS_CONTRACT_TOKEN" 50 | w3s: 51 | token: "CS_W3S_TOKEN" 52 | timeout: 10 53 | retry-count: 100 54 | eth: 55 | url: "https://ropsten.infura.io/v3" 56 | projectid: "45630f96f9d841679dc200a7c97763d2" 57 | -------------------------------------------------------------------------------- /deploy/fullnode/docker-compose/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes auto; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 10240; 9 | } 10 | 11 | http { 12 | sendfile on; 13 | tcp_nopush on; 14 | tcp_nodelay on; 15 | 16 | keepalive_timeout 65; 17 | 18 | access_log off; 19 | error_log off; 20 | 21 | include mime.types; 22 | default_type application/octet-stream; 23 | 24 | gzip on; 25 | gzip_vary on; 26 | gzip_proxied any; 27 | gzip_comp_level 6; 28 | 29 | server { 30 | listen 80 default_server; 31 | 32 | server_name dash.flowshield.xyz; #here is your domain 33 | 34 | root /usr/share/nginx/html; 35 | index index.html; 36 | 37 | location ^~ /api/ { 38 | proxy_pass http://flowshield-backend:8080; 39 | } 40 | 41 | location ^~ /a/ { 42 | proxy_pass http://flowshield-backend:8080; 43 | } 44 | 45 | location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ { 46 | expires 30d; 47 | access_log off; 48 | } 49 | 50 | location ~ .*\.(js|css)?$ { 51 | expires 7d; 52 | access_log off; 53 | } 54 | 55 | location / { 56 | try_files $uri $uri/ /index.html; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /verifier/pkg/confer/config_app.go: -------------------------------------------------------------------------------- 1 | package confer 2 | 3 | import "github.com/flowshield/flowshield/verifier/pkg/util" 4 | 5 | func ConfigAppGetString(key string, defaultConfig string) string { 6 | config := ConfigAppGet(key) 7 | if config == nil { 8 | return defaultConfig 9 | } else { 10 | configStr := config.(string) 11 | if util.UtilIsEmpty(configStr) { 12 | configStr = defaultConfig 13 | } 14 | return configStr 15 | } 16 | } 17 | 18 | func ConfigAppGetInt(key string, defaultConfig int) int { 19 | config := ConfigAppGet(key) 20 | if config == nil { 21 | return defaultConfig 22 | } else { 23 | configInt := config.(int) 24 | if configInt == 0 { 25 | configInt = defaultConfig 26 | } 27 | return configInt 28 | } 29 | } 30 | 31 | func ConfigAppGet(key string) interface{} { 32 | globalConfig.RLock() 33 | defer globalConfig.RUnlock() 34 | //将配置文件中的app字段转为map 35 | config, exists := globalConfig.App[key] 36 | if !exists { 37 | return nil 38 | } 39 | return config 40 | } 41 | 42 | func ConfigEnvGet() string { 43 | strEnv := ConfigAppGet("env") 44 | return strEnv.(string) 45 | } 46 | 47 | func ConfigEnvIsDev() bool { 48 | env := ConfigEnvGet() 49 | if env == "dev" || env == "debug" { 50 | return true 51 | } 52 | return false 53 | } 54 | 55 | func ConfigEnvIsBeta() bool { 56 | env := ConfigEnvGet() 57 | if env == "beta" { 58 | return true 59 | } 60 | return false 61 | } 62 | -------------------------------------------------------------------------------- /verifier/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/flowshield/flowshield/verifier/verify" 11 | 12 | "github.com/flowshield/flowshield/verifier/server" 13 | "github.com/urfave/cli" 14 | _ "go.uber.org/automaxprocs" 15 | ) 16 | 17 | func main() { 18 | app := cli.NewApp() 19 | app.Name = "verifier" 20 | app.Author = "TS" 21 | app.Flags = []cli.Flag{ 22 | cli.StringFlag{ 23 | Name: "c", 24 | Value: "config.yaml", 25 | Usage: "config file url", 26 | }, 27 | } 28 | app.Before = server.InitService 29 | app.Action = func(c *cli.Context) error { 30 | if err := verify.VerObj.Run(context.TODO()); err != nil { 31 | return err 32 | } 33 | server.RunHTTP() 34 | return nil 35 | } 36 | //app.After = func(c *cli.Context) error { 37 | //exitSignal() 38 | //return nil 39 | //} 40 | err := app.Run(os.Args) 41 | if err != nil { 42 | panic("app run error:" + err.Error()) 43 | } 44 | } 45 | 46 | func exitSignal() { 47 | sigs := make(chan os.Signal, 1) 48 | signal.Notify(sigs, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) 49 | for sig := range sigs { 50 | switch sig { 51 | case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: 52 | fmt.Println("Bye!") 53 | os.Exit(0) 54 | case syscall.SIGHUP: 55 | fmt.Println("+++++++++++++++++++++++++++++") 56 | default: 57 | fmt.Println(sig) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /fullnode/agent/user.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "fmt" 5 | "runtime/debug" 6 | "time" 7 | 8 | "github.com/flowshield/flowshield/fullnode/app/v1/user/model/mmysql" 9 | 10 | mysqlUser "github.com/flowshield/flowshield/fullnode/app/v1/user/dao/mysql" 11 | serviceUser "github.com/flowshield/flowshield/fullnode/app/v1/user/service" 12 | "github.com/flowshield/flowshield/fullnode/pkg/logger" 13 | ) 14 | 15 | // SyncUserBindStatus 每30秒轮循未绑定的用户,判断是否已绑定 16 | func SyncUserBindStatus() { 17 | closeChan := make(chan interface{}) // 信号监控 18 | go func() { 19 | for range closeChan { 20 | go handleUserBindStatus(closeChan) 21 | } 22 | }() 23 | go handleUserBindStatus(closeChan) 24 | } 25 | 26 | func handleUserBindStatus(closeChan chan<- interface{}) { 27 | userDao := mysqlUser.NewUser(nil) 28 | defer func() { 29 | if err := recover(); err != nil { 30 | logger.Errorf(nil, "handleUserBindStatus stacktrace from panic:\n"+string(debug.Stack()), fmt.Errorf("%v", err)) 31 | } 32 | closeChan <- struct{}{} 33 | }() 34 | for { 35 | select { 36 | case <-time.After(time.Second * 10): 37 | userList, err := userDao.GetUserByStatus(mmysql.UnBind) 38 | if err != nil { 39 | logger.Errorf(nil, "handleUserBindStatus get user by status error: %v", err) 40 | continue 41 | } 42 | for _, value := range userList { 43 | time.Sleep(5 * time.Second) 44 | serviceUser.CheckAndBindUser(&value) 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /provider/README.md: -------------------------------------------------------------------------------- 1 | # FlowShield Provider 2 | 3 | As a service network provider program, miners can deploy network services through this program to obtain rewards. 4 | 5 | The program automatically finds through P2P networking and uses PubSub mode to share its own data. 6 | 7 | Currently, websocket traffic transmission is supported. 8 | 9 | ## How does it work? 10 | 11 | ### Scene Introduction 12 | image 13 | 14 | ## Getting Started 15 | 16 | ### Configuration 17 | 18 | In the configs directory, the user stores the project configuration file with the file name: config.toml, which can be modified according to your own needs 19 | 20 | During deployment, you can refer to our current [deployment example](https://github.com/FlowShield/FlowShield/tree/main/deploy/provider) and modify the corresponding configuration 21 | 22 | 23 | ### Quickstart 24 | ```shell 25 | $ make 26 | $ ./bin/provider -c ./configs/config.toml 27 | ``` 28 | 29 | ## License 30 | FlowShield-Provider uses Apache 2.0 license. See [license](LICENSE) directory for details 31 | 32 | ## Disclaimers 33 | When you use this software, you have agreed and declared that the author, maintainer and contributor of this software are not responsible for any risks, costs or problems you encounter. If you find a software defect or bug, please submit a patch to help improve! 34 | -------------------------------------------------------------------------------- /verifier/verify/provider.go: -------------------------------------------------------------------------------- 1 | package verify 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Provider struct { 8 | PeerId string `json:"peer_id"` 9 | Addr string `json:"addr"` 10 | Port int `json:"port"` 11 | IP string `json:"ip"` 12 | Loc string `json:"loc"` 13 | Colo string `json:"colo"` 14 | Price uint `json:"price"` 15 | Order []*Order `json:"order"` 16 | } 17 | 18 | func providers(orders []*OrderMysql) (providers []*Provider, err error) { 19 | if orders == nil || len(orders) == 0 { 20 | return 21 | } 22 | var providerMap = make(map[string][]*OrderMysql) 23 | for _, value := range orders { 24 | providerMap[value.PeerID] = append(providerMap[value.PeerID], value) 25 | } 26 | for key, value := range providerMap { 27 | orderSli := make([]*Order, 0) 28 | for _, v := range value { 29 | orderObj := &Order{ 30 | PeerID: v.PeerID, 31 | Port: v.Port, 32 | OrderID: v.UUID, 33 | StartTime: time.Unix(v.UpdatedAt, 0), 34 | EndTime: time.Unix(v.UpdatedAt, 0).Add(time.Duration(v.Duration) * 60 * 60), 35 | Healthy: nil, 36 | } 37 | orderSli = append(orderSli, orderObj) 38 | } 39 | provider := &Provider{ 40 | PeerId: key, 41 | Addr: value[0].NodeIP, 42 | //Port: value[0].Port, 43 | IP: value[0].NodeIP, 44 | //Loc: "", 45 | //Colo: "", 46 | //Price: 0, 47 | Order: orderSli, 48 | } 49 | providers = append(providers, provider) 50 | } 51 | return 52 | } 53 | -------------------------------------------------------------------------------- /fullnode/agent/client.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "fmt" 5 | "runtime/debug" 6 | "time" 7 | 8 | "github.com/flowshield/flowshield/fullnode/app/v1/access/service" 9 | 10 | "github.com/flowshield/flowshield/fullnode/app/v1/access/model/mmysql" 11 | 12 | "github.com/flowshield/flowshield/fullnode/app/v1/access/dao/mysql" 13 | "github.com/flowshield/flowshield/fullnode/app/v1/access/model/mparam" 14 | 15 | "github.com/flowshield/flowshield/fullnode/pkg/logger" 16 | ) 17 | 18 | // SyncClientOrderStatus 每30秒轮循10分钟内的订单,判断是否已支付 19 | func SyncClientOrderStatus() { 20 | closeChan := make(chan interface{}) // 信号监控 21 | go func() { 22 | for range closeChan { 23 | go handleClientOrderStatus(closeChan) 24 | } 25 | }() 26 | go handleClientOrderStatus(closeChan) 27 | } 28 | 29 | func handleClientOrderStatus(closeChan chan<- interface{}) { 30 | clientDao := mysql.NewClient(nil) 31 | defer func() { 32 | if err := recover(); err != nil { 33 | logger.Errorf(nil, "handleClientOrderStatus stacktrace from panic:\n"+string(debug.Stack()), fmt.Errorf("%v", err)) 34 | } 35 | closeChan <- struct{}{} 36 | }() 37 | for { 38 | select { 39 | case <-time.After(time.Second * 30): 40 | clientList, err := clientDao.CheckStatusClient(&mparam.CheckStatus{ 41 | Status: mmysql.WaitingPaid, 42 | Duration: 10, 43 | }) 44 | if err != nil { 45 | continue 46 | } 47 | for _, value := range clientList { 48 | time.Sleep(5 * time.Second) 49 | service.NotifyClient(nil, &mparam.NotifyClient{UUID: value.UUID}) 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /fullnode/app/v1/user/model/mapi/github.go: -------------------------------------------------------------------------------- 1 | package mapi 2 | 3 | type GithubUser struct { 4 | Login string `json:"login"` 5 | ID int `json:"id"` 6 | NodeID string `json:"node_id"` 7 | AvatarURL string `json:"avatar_url"` 8 | GravatarID string `json:"gravatar_id"` 9 | URL string `json:"url"` 10 | HtmlUrl string `json:"html_url"` 11 | FollowersURL string `json:"followers_url"` 12 | FollowingURL string `json:"following_url"` 13 | GistsURL string `json:"gists_url"` 14 | StarredURL string `json:"starred_url"` 15 | SubscriptionsURL string `json:"subscriptions_url"` 16 | OrganizationsURL string `json:"organizations_url"` 17 | ReposURL string `json:"repos_url"` 18 | EventsURL string `json:"events_url"` 19 | ReceivedEventsURL string `json:"received_events_url"` 20 | Type string `json:"type"` 21 | SiteAdmin bool `json:"site_admin"` 22 | Name string `json:"name"` 23 | Company string `json:"company"` 24 | Blog string `json:"blog"` 25 | Location string `json:"location"` 26 | Email string `json:"email"` 27 | Hireable bool `json:"hireable"` 28 | Bio string `json:"bio"` 29 | TwitterUserName string `json:"twitter_username"` 30 | PublicRepos int `json:"public_repos"` 31 | PublicGists int `json:"public_gits"` 32 | Followers int `json:"followers"` 33 | Following int `json:"following"` 34 | CreatedAt string `json:"created_at"` 35 | UpdatedAt string `json:"updated_at"` 36 | } 37 | -------------------------------------------------------------------------------- /fullnode/pconst/api.go: -------------------------------------------------------------------------------- 1 | package pconst 2 | 3 | // Constants for API 4 | const ( 5 | IAPIRoot = "/i" 6 | APPAPIRoot = "/app" 7 | APIAPIRoot = "/api" 8 | ADMINAPIRoot = "/admin" 9 | APIV1Version = "v1" 10 | APIV2Version = "v2" 11 | APIV3Version = "v3" 12 | APIV4Version = "v4" 13 | IAPIV1URL = IAPIRoot + "/" + APIV1Version 14 | IAPIV2URL = IAPIRoot + "/" + APIV2Version 15 | IAPIV3URL = IAPIRoot + "/" + APIV3Version 16 | IAPIV4URL = IAPIRoot + "/" + APIV4Version 17 | APPAPIV1URL = APPAPIRoot + "/" + APIV1Version 18 | APIAPIV1URL = APIAPIRoot + "/" + APIV1Version 19 | ADMINAPIV1URL = ADMINAPIRoot + "/" + APIV1Version 20 | APPAPIV2URL = APPAPIRoot + "/" + APIV2Version 21 | APIAPIV2URL = APIAPIRoot + "/" + APIV2Version 22 | //time 23 | 24 | TIME_FORMAT_Y_M_D_H_I_S_MS = "2006-01-02 15:04:05.000" 25 | TIME_FORMAT_Y_M_D_H_I_S = "2006-01-02 15:04:05" 26 | TIME_FORMAT_Y_M_D_H_I_S_2 = "2006/01/02 15:04:05" 27 | TIME_FORMAT_Y_M_D = "2006.01.02" 28 | TIME_FORMAT_Y_M_D_ = "2006-01-02" 29 | TIME_FORMAT_Y_MS_D_ = "2006-January-02" 30 | TIME_FORMAT_M_D_H_I = "01.02 15:04" 31 | TIME_FORMAT_H_I = "15:04" 32 | 33 | TIME_ONE_SECOND = 1 34 | TIME_TWO_SECOND = 2 35 | TIME_ONE_MINUTE = 60 36 | TIME_TEN_MINUTE = 600 37 | TIME_ONE_HOUR = 3600 38 | TIME_ONE_DAY = 86400 39 | TIME_THREE_DAY = 259200 40 | TIME_ONE_WEEK = 604800 41 | TIME_ONE_MONTH = 2592000 42 | TIME_ONE_YEAR = 31536000 43 | 44 | //common 45 | 46 | COMMON_PAGE_LIMIT_NUM_10 = 10 47 | COMMON_PAGE_LIMIT_NUM_20 = 20 48 | COMMON_PAGE_LIMIT_NUM_MAX = 20 49 | 50 | COMMON_ERROR_RETRY_LIMIT_NUM = 5 51 | ) 52 | -------------------------------------------------------------------------------- /portal/src/App.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 64 | 70 | -------------------------------------------------------------------------------- /verifier/pconst/api.go: -------------------------------------------------------------------------------- 1 | package pconst 2 | 3 | // Constants for API 4 | const ( 5 | IAPIRoot = "/i" 6 | APPAPIRoot = "/app" 7 | APIAPIRoot = "/api" 8 | ADMINAPIRoot = "/admin" 9 | APIV1Version = "v1" 10 | APIV2Version = "v2" 11 | APIV3Version = "v3" 12 | APIV4Version = "v4" 13 | IAPIV1URL = IAPIRoot + "/" + APIV1Version 14 | IAPIV2URL = IAPIRoot + "/" + APIV2Version 15 | IAPIV3URL = IAPIRoot + "/" + APIV3Version 16 | IAPIV4URL = IAPIRoot + "/" + APIV4Version 17 | APPAPIV1URL = APPAPIRoot + "/" + APIV1Version 18 | APIAPIV1URL = APIAPIRoot + "/" + APIV1Version 19 | ADMINAPIV1URL = ADMINAPIRoot + "/" + APIV1Version 20 | APPAPIV2URL = APPAPIRoot + "/" + APIV2Version 21 | APIAPIV2URL = APIAPIRoot + "/" + APIV2Version 22 | //time 23 | 24 | TIME_FORMAT_Y_M_D_H_I_S_MS = "2006-01-02 15:04:05.000" 25 | TIME_FORMAT_Y_M_D_H_I_S = "2006-01-02 15:04:05" 26 | TIME_FORMAT_Y_M_D_H_I_S_2 = "2006/01/02 15:04:05" 27 | TIME_FORMAT_Y_M_D = "2006.01.02" 28 | TIME_FORMAT_Y_M_D_ = "2006-01-02" 29 | TIME_FORMAT_Y_MS_D_ = "2006-January-02" 30 | TIME_FORMAT_M_D_H_I = "01.02 15:04" 31 | TIME_FORMAT_H_I = "15:04" 32 | 33 | TIME_ONE_SECOND = 1 34 | TIME_TWO_SECOND = 2 35 | TIME_ONE_MINUTE = 60 36 | TIME_TEN_MINUTE = 600 37 | TIME_ONE_HOUR = 3600 38 | TIME_ONE_DAY = 86400 39 | TIME_THREE_DAY = 259200 40 | TIME_ONE_WEEK = 604800 41 | TIME_ONE_MONTH = 2592000 42 | TIME_ONE_YEAR = 31536000 43 | 44 | //common 45 | 46 | COMMON_PAGE_LIMIT_NUM_10 = 10 47 | COMMON_PAGE_LIMIT_NUM_20 = 20 48 | COMMON_PAGE_LIMIT_NUM_MAX = 20 49 | 50 | COMMON_ERROR_RETRY_LIMIT_NUM = 5 51 | ) 52 | -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "PausableUpgradeable", 4 | "sourceName": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": false, 11 | "internalType": "uint8", 12 | "name": "version", 13 | "type": "uint8" 14 | } 15 | ], 16 | "name": "Initialized", 17 | "type": "event" 18 | }, 19 | { 20 | "anonymous": false, 21 | "inputs": [ 22 | { 23 | "indexed": false, 24 | "internalType": "address", 25 | "name": "account", 26 | "type": "address" 27 | } 28 | ], 29 | "name": "Paused", 30 | "type": "event" 31 | }, 32 | { 33 | "anonymous": false, 34 | "inputs": [ 35 | { 36 | "indexed": false, 37 | "internalType": "address", 38 | "name": "account", 39 | "type": "address" 40 | } 41 | ], 42 | "name": "Unpaused", 43 | "type": "event" 44 | }, 45 | { 46 | "inputs": [], 47 | "name": "paused", 48 | "outputs": [ 49 | { 50 | "internalType": "bool", 51 | "name": "", 52 | "type": "bool" 53 | } 54 | ], 55 | "stateMutability": "view", 56 | "type": "function" 57 | } 58 | ], 59 | "bytecode": "0x", 60 | "deployedBytecode": "0x", 61 | "linkReferences": {}, 62 | "deployedLinkReferences": {} 63 | } 64 | -------------------------------------------------------------------------------- /portal/src/views/login.vue: -------------------------------------------------------------------------------- 1 | 26 | 49 | 54 | -------------------------------------------------------------------------------- /fullnode/app/v1/access/model/mparam/client.go: -------------------------------------------------------------------------------- 1 | package mparam 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/flowshield/flowshield/fullnode/app/base/mdb" 7 | "github.com/flowshield/flowshield/fullnode/app/v1/access/model/mmysql" 8 | ) 9 | 10 | type ClientList struct { 11 | mdb.Paginate 12 | Name string `json:"name" form:"name"` 13 | PeerID string `json:"peer_id"` 14 | ResourceCID int `json:"resource_cid" form:"resource_cid"` 15 | Working bool `json:"working" form:"working"` 16 | } 17 | 18 | type AddClient struct { 19 | PeerID string `json:"peer_id" form:"peer_id" binding:"required"` 20 | Name string `json:"name" form:"name" binding:"required"` 21 | //Port int `json:"port" form:"port" binding:"required"` // 443 22 | Duration uint `json:"duration" form:"duration" binding:"required"` // 使用时间:小时 23 | ResourceCID string `json:"resource_cid" binding:"required"` 24 | } 25 | 26 | type EditClient struct { 27 | ID uint64 `json:"id" form:"id" binding:"required"` 28 | ServerID uint64 `json:"server_id" form:"server_id" binding:"required"` 29 | Name string `json:"name" form:"name" binding:"required"` 30 | Port int `json:"port" form:"port" binding:"required"` // 443 31 | Expire int `json:"expire" form:"expire" binding:"required"` // 过期时间:天 32 | Target mmysql.ClientTarget `json:"target" binding:"required"` 33 | } 34 | 35 | type NotifyClient struct { 36 | UUID string `json:"uuid" form:"uuid" binding:"required"` 37 | } 38 | 39 | type CheckStatus struct { 40 | Status uint `json:"status"` 41 | Duration time.Duration `json:"duration"` 42 | } 43 | -------------------------------------------------------------------------------- /fullnode/app/v1/user/controller/user.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | 8 | "github.com/flowshield/flowshield/fullnode/app/v1/user/service" 9 | "github.com/flowshield/flowshield/fullnode/pconst" 10 | "github.com/flowshield/flowshield/fullnode/pkg/response" 11 | "github.com/flowshield/flowshield/fullnode/pkg/util" 12 | "github.com/gin-gonic/contrib/sessions" 13 | "github.com/gin-gonic/gin" 14 | ) 15 | 16 | func Login(c *gin.Context) { 17 | redirectURL, code := service.GetRedirectURL(c) 18 | if code != pconst.CODE_ERROR_OK { 19 | // TODO Redirect to BadRequest page 20 | c.AbortWithError(http.StatusBadRequest, fmt.Errorf("company %s not support", c.Param("company"))) 21 | return 22 | } 23 | c.Redirect(http.StatusSeeOther, redirectURL) 24 | } 25 | 26 | func UserDetail(c *gin.Context) { 27 | response.UtilResponseReturnJson(c, pconst.CODE_ERROR_OK, util.User(c)) 28 | } 29 | 30 | func Oauth2Callback(c *gin.Context) { 31 | session := sessions.Default(c) 32 | state := session.Get("state") 33 | if state != c.Query("state") { 34 | _ = c.AbortWithError(http.StatusUnauthorized, errors.New("state error")) 35 | return 36 | } 37 | if len(c.Query("code")) == 0 { 38 | _ = c.AbortWithError(http.StatusBadRequest, errors.New("code error")) 39 | } 40 | service.Oauth2Callback(c, session, c.Query("code")) 41 | } 42 | 43 | // @Summary UserRefresh 44 | // @Description 用户刷新token 45 | // @Tags ZTA 46 | // @Accept json 47 | // @Produce json 48 | // @Success 200 {object} controller.Res 49 | // @Router /user/refresh [post] 50 | func UserRefresh(c *gin.Context) { 51 | code := service.UserRefresh(c) 52 | response.UtilResponseReturnJson(c, code, nil) 53 | } 54 | -------------------------------------------------------------------------------- /fullnode/pconst/code.go: -------------------------------------------------------------------------------- 1 | package pconst 2 | 3 | const ( 4 | //common 5 | CODE_ERROR_OK = 0 6 | CODE_COMMON_OK = 1001 7 | //CODE_COMMON_ACCESS_FAIL = 1002 8 | CODE_COMMON_SERVER_BUSY = 1003 9 | CODE_COMMON_PARAMS_INCOMPLETE = 1004 10 | CODE_COMMON_DATA_NOT_EXIST = 1006 11 | CODE_COMMON_DATA_ALREADY_EXIST = 1007 12 | CODE_VICTORIA_METRICS_ERR = 1008 13 | CODE_DATA_HAS_RELATION = 1009 14 | CODE_DATA_WRONG_STATE = 1010 15 | CODE_API_BAD_REQUEST = 1011 16 | CODE_NOT_FOUND = 1012 17 | 18 | CODE_COMMON_USER_NO_LOGIN = 1005 19 | CODE_COMMON_ACCESS_FORBIDDEN = 1013 20 | ERROR_AUTH_CHECK_TOKEN_FAIL = 1014 21 | ERROR_AUTH_CHECK_TOKEN_TIMEOUT = 1015 22 | ERROR_AUTH_TOKEN = 1016 23 | ERROR_AUTH = 1017 24 | CODE_COMMON_USER_INVALID = 1018 25 | ERROR_AUTH_CHECK_SECRET_EXPIRED = 1019 26 | ERROR_CHECK_CAPTCHA = 1020 27 | ) 28 | 29 | /* 30 | 注册中心相关 31 | */ 32 | const ( 33 | STATIC_REGISTER_CENTER_TYPE = 1 34 | DYNAMIC_REGISTER_CENTER_TYPE = 2 35 | ) 36 | 37 | // SERVICE_RULE_EXPIRE 治理规则redis过期时间 38 | const SERVICE_RULE_EXPIRE = 60 * 60 * 25 39 | 40 | const SITE = "IDG_SITEUID" 41 | const CLUSTER = "IDG_CLUSTERUID" 42 | const NAMESPACE = "NAMESPACE" 43 | const SENTRY_NAMESPACE = "SENTRY_NAMESPACE" 44 | const DEFAULT_NAMESPACE = "msp" 45 | const DEFAULT_SENTRY_NAMESPACE = "sentry" 46 | const SITE_DOMAIN = "SITE_DOMAIN" 47 | const DEFAULT_SITE_DOMAIN = "gw002.oneitfarm.com" 48 | const BLOCKCHAIN_SYNCING = 1 49 | const BLOCKCHAIN_FINISHED = 2 50 | 51 | const ( 52 | HTTPRouteGroup = "HTTPRouteGroup" 53 | TCPRoute = "TCPRoute" 54 | UDPRoute = "UDPRoute" 55 | ) 56 | -------------------------------------------------------------------------------- /verifier/pconst/code.go: -------------------------------------------------------------------------------- 1 | package pconst 2 | 3 | const ( 4 | //common 5 | CODE_ERROR_OK = 0 6 | CODE_COMMON_OK = 1001 7 | //CODE_COMMON_ACCESS_FAIL = 1002 8 | CODE_COMMON_SERVER_BUSY = 1003 9 | CODE_COMMON_PARAMS_INCOMPLETE = 1004 10 | CODE_COMMON_DATA_NOT_EXIST = 1006 11 | CODE_COMMON_DATA_ALREADY_EXIST = 1007 12 | CODE_VICTORIA_METRICS_ERR = 1008 13 | CODE_DATA_HAS_RELATION = 1009 14 | CODE_DATA_WRONG_STATE = 1010 15 | CODE_API_BAD_REQUEST = 1011 16 | CODE_NOT_FOUND = 1012 17 | 18 | CODE_COMMON_USER_NO_LOGIN = 1005 19 | CODE_COMMON_ACCESS_FORBIDDEN = 1013 20 | ERROR_AUTH_CHECK_TOKEN_FAIL = 1014 21 | ERROR_AUTH_CHECK_TOKEN_TIMEOUT = 1015 22 | ERROR_AUTH_TOKEN = 1016 23 | ERROR_AUTH = 1017 24 | CODE_COMMON_USER_INVALID = 1018 25 | ERROR_AUTH_CHECK_SECRET_EXPIRED = 1019 26 | ERROR_CHECK_CAPTCHA = 1020 27 | ) 28 | 29 | /* 30 | 注册中心相关 31 | */ 32 | const ( 33 | STATIC_REGISTER_CENTER_TYPE = 1 34 | DYNAMIC_REGISTER_CENTER_TYPE = 2 35 | ) 36 | 37 | // SERVICE_RULE_EXPIRE 治理规则redis过期时间 38 | const SERVICE_RULE_EXPIRE = 60 * 60 * 25 39 | 40 | const SITE = "IDG_SITEUID" 41 | const CLUSTER = "IDG_CLUSTERUID" 42 | const NAMESPACE = "NAMESPACE" 43 | const SENTRY_NAMESPACE = "SENTRY_NAMESPACE" 44 | const DEFAULT_NAMESPACE = "msp" 45 | const DEFAULT_SENTRY_NAMESPACE = "sentry" 46 | const SITE_DOMAIN = "SITE_DOMAIN" 47 | const DEFAULT_SITE_DOMAIN = "gw002.oneitfarm.com" 48 | const BLOCKCHAIN_SYNCING = 1 49 | const BLOCKCHAIN_FINISHED = 2 50 | 51 | const ( 52 | HTTPRouteGroup = "HTTPRouteGroup" 53 | TCPRoute = "TCPRoute" 54 | UDPRoute = "UDPRoute" 55 | ) 56 | -------------------------------------------------------------------------------- /fullnode/examples/helm/templates/deployment-portal.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: zaportal 6 | name: zaportal 7 | spec: 8 | replicas: {{ .Values.replicas }} 9 | selector: 10 | matchLabels: 11 | app: zaportal 12 | strategy: {} 13 | template: 14 | metadata: 15 | labels: 16 | app: zaportal 17 | spec: 18 | volumes: 19 | - name: zaportal-nginx 20 | configMap: 21 | name: zaportal-nginx 22 | containers: 23 | - image: {{ .Values.deployment.zaportal.repository }}:{{ .Values.deployment.zaportal.tag }} 24 | name: zaportal 25 | ports: 26 | - name: http 27 | containerPort: 80 28 | resources: 29 | {{- toYaml .Values.deployment.zaportal.resources | nindent 10 }} 30 | volumeMounts: 31 | - name: zaportal-nginx 32 | mountPath: /etc/nginx/nginx.conf 33 | subPath: nginx.conf 34 | - image: {{ .Values.deployment.zamanager.repository }}:{{ .Values.deployment.zamanager.tag }} 35 | name: zamanager 36 | resources: 37 | {{- toYaml .Values.deployment.zamanager.resources | nindent 10 }} 38 | env: 39 | {{- range $key, $value := .Values.deployment.zamanager.env }} 40 | - name: {{ $key }} 41 | value: "{{ $value }}" 42 | {{- end }} 43 | {{- with .Values.nodeSelector }} 44 | nodeSelector: 45 | {{- toYaml . | nindent 8 }} 46 | {{- end }} 47 | {{- with .Values.affinity }} 48 | affinity: 49 | {{- toYaml . | nindent 8 }} 50 | {{- end }} 51 | {{- with .Values.tolerations }} 52 | tolerations: 53 | {{- toYaml . | nindent 8 }} 54 | {{- end }} 55 | -------------------------------------------------------------------------------- /deploy/provider/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | provider: 4 | image: zhangshuainbb/flowshield-provider:v0.0.1 5 | network_mode: host 6 | restart: always 7 | environment: 8 | PR_LOG_LEVEL: '5' 9 | PR_APP_LOCAL_ADDR: 'xxx' 10 | PR_APP_LOCAL_PORT: '5091' 11 | PR_WEB3_PRICE: '20' 12 | PR_WEB3_PRIVATE_KEY: 'xxx' 13 | PR_WEB3_CONTRACT_TOKEN: '0x3A35207918FEE0F59a32a1a36B58A758B4F222de' 14 | PR_WEB3_W3S_TOKEN: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDU4MUJkZEVGNTA3MDlmZjIzQzEwN0Q5YUU2NEVlMjc5M0IyMzk3NWMiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2NTY2NDc2MDM2MjUsIm5hbWUiOiJjbG91ZHNsaXQifQ.7iUZuCDn1SNn7CxuR_kdAWf9_PfpuJlqPmy7ZdB2x9U' 15 | PR_WEB3_W3S_TIMEOUT: '10' 16 | PR_WEB3_W3S_RETRY_COUNT: '100' 17 | PR_WEB3_ETH_URL: 'https://ropsten.infura.io/v3' 18 | PR_WEB3_ETH_PROJECT_ID: '45630f96f9d841679dc200a7c97763d2' 19 | PR_MYSQL_HOST: '127.0.0.1' 20 | PR_MYSQL_PORT: '23306' 21 | PR_MYSQL_USER: 'root' 22 | PR_MYSQL_PASSWORD: '123456' 23 | deploy: 24 | resources: 25 | limits: 26 | cpus: '1.00' 27 | memory: 1G 28 | reservations: 29 | cpus: '0.50' 30 | memory: 500M 31 | depends_on: 32 | icefiresqlite: 33 | condition: "service_healthy" 34 | 35 | icefiresqlite: 36 | image: taosheng205054/icefire-sqlite:latest 37 | restart: always 38 | healthcheck: 39 | test: [ "CMD", "mysqladmin" ,"ping", "-h", "127.0.0.1", "-P", "23306","-uroot","-p123456" ] 40 | timeout: 20s 41 | retries: 10 42 | ports: 43 | - 23306:23306 44 | volumes: 45 | - ./db/sqlite.db:/app/db/sqlite.db 46 | - "./sqlite_config.yaml:/app/config/config.yaml" 47 | -------------------------------------------------------------------------------- /fullnode/app/v1/controlplane/controller/machine.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/app/base/controller" 5 | "github.com/flowshield/flowshield/fullnode/app/v1/controlplane/model/mparam" 6 | "github.com/flowshield/flowshield/fullnode/app/v1/controlplane/service" 7 | "github.com/flowshield/flowshield/fullnode/pkg/response" 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | // @Summary LoginUrl 12 | // @Description 根据机器码获取客户端鉴权的url 13 | // @Tags ZTA ControlPlane 14 | // @Produce json 15 | // @Param machine_id path string true "machine_id" 16 | // @Success 200 {object} controller.Res 17 | // @Router /controlplane/machine/{machine_id} [get] 18 | func LoginUrl(c *gin.Context) { 19 | code, data := service.GetLoginUrl(c, c.Param("machine_id")) 20 | response.UtilResponseReturnJson(c, code, data) 21 | } 22 | 23 | // @Summary MachineOauth 24 | // @Description 机器鉴权 25 | // @Tags ZTA ControlPlane 26 | // @Produce json 27 | // @Param hash path string true "hash" 28 | // @Success 200 {object} controller.Res 29 | // @Router /a/{hash} [get] 30 | func MachineOauth(c *gin.Context) { 31 | service.MachineOauth(c, c.Param("hash")) 32 | } 33 | 34 | // @Summary MachineLongPoll 35 | // @Description 机器鉴权 36 | // @Tags ZTA ControlPlane 37 | // @Produce json 38 | // @Param category query string true "轮询的主题" 39 | // @Param timeout query int true "超时时间,单位:秒" 40 | // @Success 200 {object} controller.Res 41 | // @Router /machine/auth/poll [get] 42 | func MachineLongPoll(c *gin.Context) { 43 | param := mparam.MachineLongPoll{} 44 | b, code := controller.BindParams(c, ¶m) 45 | if !b { 46 | response.UtilResponseReturnJsonFailed(c, code) 47 | return 48 | } 49 | data, code := service.MachineLongPoll(c, param) 50 | response.UtilResponseReturnJson(c, code, data) 51 | } 52 | -------------------------------------------------------------------------------- /fullnode/route/access/access.go: -------------------------------------------------------------------------------- 1 | package access 2 | 3 | import ( 4 | "net/http" 5 | 6 | v1 "github.com/flowshield/flowshield/fullnode/app/v1/access/controller" 7 | "github.com/flowshield/flowshield/fullnode/pconst" 8 | "github.com/flowshield/flowshield/fullnode/pkg/middle" 9 | "github.com/flowshield/flowshield/fullnode/pkg/util" 10 | 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | func checkDaoMaster(c *gin.Context) { 15 | // 判断当前用户是否是Dao主 16 | user := util.User(c) 17 | if user == nil || !user.Master { 18 | c.JSON(http.StatusForbidden, gin.H{ 19 | "code": pconst.CODE_COMMON_ACCESS_FORBIDDEN, 20 | "message": "permission denied", 21 | }) 22 | c.Abort() 23 | } 24 | } 25 | 26 | func APIAccess(parentRoute gin.IRouter) { 27 | r := parentRoute.Group("access", middle.Oauth2()) 28 | //r := parentRoute.Group("access") 29 | { 30 | resource := r.Group("resource") 31 | { 32 | resource.GET("", v1.ResourceList) 33 | resource.POST("", checkDaoMaster, v1.AddResource) 34 | //resource.PUT("", v1.EditResource) 35 | resource.DELETE("/:uuid", checkDaoMaster, v1.DelResource) 36 | } 37 | //relay := r.Group("relay") 38 | //{ 39 | // relay.GET("", v1.RelayList) 40 | // relay.POST("", v1.AddRelay) 41 | // relay.PUT("", v1.EditRelay) 42 | // relay.DELETE("/:uuid", v1.DelRelay) 43 | //} 44 | //server := r.Group("server") 45 | //{ 46 | // server.GET("", v1.ServerList) 47 | // server.POST("", v1.AddServer) 48 | // server.PUT("", v1.EditServer) 49 | // server.DELETE("/:uuid", v1.DelServer) 50 | //} 51 | client := r.Group("client") 52 | { 53 | client.GET("", v1.ClientList) 54 | client.POST("", v1.AddClient) 55 | client.POST("/notify", v1.NotifyClient) 56 | //client.PUT("", v1.EditClient) 57 | //client.DELETE("/:uuid", v1.DelClient) 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /fullnode/Makefile: -------------------------------------------------------------------------------- 1 | GOPROXY=https://goproxy.cn,direct 2 | 3 | PROG=bin/fullnode 4 | 5 | 6 | SRCS=. 7 | 8 | # installation 9 | INSTALL_PREFIX=/usr/local/fullnode 10 | 11 | # Configure the installation directory 12 | CONF_INSTALL_PREFIX=/usr/local/fullnode 13 | 14 | # git commit hash 15 | COMMIT_HASH=$(shell git rev-parse --short HEAD || echo "GitNotFound") 16 | 17 | # Compilation date 18 | BUILD_DATE=$(shell date '+%Y-%m-%d %H:%M:%S') 19 | 20 | # Compilation conditions 21 | CFLAGS = -ldflags "-s -w -X \"main.BuildVersion=${COMMIT_HASH}\" -X \"main.BuildDate=$(BUILD_DATE)\"" 22 | 23 | all: 24 | if [ ! -d "./bin/" ]; then \ 25 | mkdir bin; \ 26 | fi 27 | GOPROXY=$(GOPROXY) CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(CFLAGS) -o $(PROG) $(SRCS) 28 | 29 | # Compile race version 30 | race: 31 | if [ ! -d "./bin/" ]; then \ 32 | mkdir bin; \ 33 | fi 34 | go build $(CFLAGS) -race -o $(PROG) $(SRCS) 35 | 36 | # release version 37 | RELEASE_DATE = $(shell date '+%Y%m%d%H%M%S') 38 | RELEASE_VERSION = $(shell git rev-parse --short HEAD || echo "GitNotFound") 39 | RELEASE_DIR=release_bin 40 | RELEASE_BIN_NAME=fullnode 41 | release: 42 | if [ ! -d "./$(RELEASE_DIR)/$(RELEASE_DATE)_$(RELEASE_VERSION)" ]; then \ 43 | mkdir ./$(RELEASE_DIR)/$(RELEASE_DATE)_$(RELEASE_VERSION); \ 44 | fi 45 | go build $(CFLAGS) -o $(RELEASE_DIR)/$(RELEASE_DATE)_$(RELEASE_VERSION)/$(RELEASE_BIN_NAME)_linux_amd64 $(SRCS) 46 | 47 | install: 48 | cp $(PROG) $(INSTALL_PREFIX)/bin 49 | 50 | if [ ! -d "${CONF_INSTALL_PREFIX}" ]; then \ 51 | mkdir $(CONF_INSTALL_PREFIX); \ 52 | fi 53 | 54 | cp -R config/* $(CONF_INSTALL_PREFIX) 55 | 56 | clean: 57 | rm -rf ./bin 58 | 59 | rm -rf $(INSTALL_PREFIX)/bin/fullnode 60 | 61 | rm -rf $(CONF_INSTALL_PREFIX) 62 | 63 | run: 64 | go run main.go 65 | 66 | run_race: 67 | go run --race main.go 68 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | build-ca: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v5 18 | with: 19 | go-version: 1.23.2 20 | 21 | - name: Build 22 | run: | 23 | cd ca 24 | make 25 | 26 | build-client: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v4 30 | 31 | - name: Set up Go 32 | uses: actions/setup-go@v5 33 | with: 34 | go-version: 1.18 35 | 36 | - name: Build 37 | run: | 38 | cd client 39 | make 40 | 41 | build-fullnode: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v4 45 | 46 | - name: Set up Go 47 | uses: actions/setup-go@v5 48 | with: 49 | go-version: 1.18 50 | 51 | - name: Build 52 | run: | 53 | cd fullnode 54 | make 55 | 56 | build-provider: 57 | runs-on: ubuntu-latest 58 | steps: 59 | - uses: actions/checkout@v4 60 | 61 | - name: Set up Go 62 | uses: actions/setup-go@v5 63 | with: 64 | go-version: 1.18 65 | 66 | - name: Build 67 | run: | 68 | cd provider 69 | make 70 | 71 | build-portal: 72 | runs-on: ubuntu-latest 73 | steps: 74 | - uses: actions/checkout@v4 75 | 76 | - name: Set up node.js 77 | uses: actions/setup-node@v4 78 | with: 79 | node-version: 16 80 | 81 | - name: Build 82 | run: | 83 | cd portal 84 | npm install 85 | npm run build 86 | -------------------------------------------------------------------------------- /fullnode/server/init.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/fullnode/agent" 5 | "github.com/flowshield/flowshield/fullnode/pkg/confer" 6 | "github.com/flowshield/flowshield/fullnode/pkg/logger" 7 | "github.com/flowshield/flowshield/fullnode/pkg/mysql" 8 | "github.com/flowshield/flowshield/fullnode/pkg/redis" 9 | "github.com/flowshield/flowshield/fullnode/pkg/web3/eth" 10 | "github.com/flowshield/flowshield/fullnode/pkg/web3/w3s" 11 | "github.com/urfave/cli" 12 | ) 13 | 14 | func InitService(c *cli.Context) (err error) { 15 | if err = confer.Init(c.String("c")); err != nil { 16 | return 17 | } 18 | cfg := confer.GlobalConfig() 19 | logger.Init(&logger.Config{ 20 | Level: logger.LogLevel(), 21 | Filename: logger.LogFile(), 22 | SendToFile: logger.SendLogToFile(), 23 | Development: confer.ConfigEnvIsDev(), 24 | }) 25 | if err = redis.Init(&cfg.Redis); err != nil { 26 | logger.Errorf(nil, "redis init error : %v", err) 27 | return 28 | } 29 | if err = mysql.Init(&cfg.Mysql); err != nil { 30 | logger.Errorf(nil, "mysql init error : %v", err) 31 | return 32 | } 33 | if err = w3s.Init(&cfg.Web3); err != nil { 34 | logger.Errorf(nil, "w3s init error : %v", err) 35 | return 36 | } 37 | if confer.GlobalConfig().Web3.Register == "true" { 38 | if err = eth.InitETH(&cfg.Web3); err != nil { 39 | logger.Errorf(nil, "eth init error : %v", err) 40 | return 41 | } 42 | } 43 | // 判断是否开启P2P 44 | if confer.GlobalConfig().P2P.Enable { 45 | if err = runP2P(&cfg.P2P); err != nil { 46 | logger.Errorf(nil, "p2p init error : %v", err) 47 | return 48 | } 49 | } 50 | if confer.GlobalConfig().Web3.Register == "true" && confer.GlobalConfig().P2P.Enable { 51 | // 启动订单同步检查agent 52 | go agent.SyncClientOrderStatus() 53 | go agent.SyncUserBindStatus() 54 | } 55 | return 56 | } 57 | -------------------------------------------------------------------------------- /fullnode/config_dev.yaml: -------------------------------------------------------------------------------- 1 | #APP ENV 2 | app: 3 | env: "dev" # dev,release 4 | sysname: "FlowShield" 5 | port: 80 6 | domain: http://192.168.2.80:9534 7 | 8 | #Mysql 9 | mysql: 10 | dbname: "zta" 11 | prefix: "zta_" 12 | pool: 13 | pool-min-cap: 10 14 | pool-ex-cap: 5 15 | pool-max-cap: 40 16 | pool-idle-timeout: 3600 17 | pool-wait-count: 1000 18 | pool-wai-timeout: 30 19 | write: 20 | host: "127.0.0.1" 21 | port: 23306 22 | user: "root" 23 | password: "123456" 24 | # write: 25 | # host: "192.168.2.80" 26 | # port: 3306 27 | # user: "root" 28 | # password: "123456" 29 | 30 | #Redis 31 | redis: 32 | addr: "192.168.2.80:6379" 33 | 34 | #CA 35 | ca: 36 | sign-url: "https://192.168.2.80:8581" 37 | auth-key: "0739a645a7d6601d9d45f6b237c4edeadad904f2fce53625dfdd541ec4fc8134" 38 | 39 | oauth2: 40 | client-id: "736c3c420d6091f4cac0" 41 | client-secret: "aeec3165d947ce121692ddf22ec77b7f2f0ec2bf" 42 | 43 | p2p: 44 | enable: false 45 | # account: "0x828233e3908fB45d40baC6B2F19F8A239ab7ae7d" 46 | service-discovery-id: "flowshield/provider" 47 | service-discovery-mode: "advertise" # advertise or announce 48 | service-metadata-topic: "flowshield_provider_metadata" # advertise or announce 49 | 50 | web3: 51 | register: "false" 52 | private-key: "a5042f010a7d7f5652097768612265014ec390ea6f2f281f362091a5c39f4900" 53 | contract: 54 | token: "0x3A35207918FEE0F59a32a1a36B58A758B4F222de" 55 | w3s: 56 | token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDU4MUJkZEVGNTA3MDlmZjIzQzEwN0Q5YUU2NEVlMjc5M0IyMzk3NWMiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2NTY2NDc2MDM2MjUsIm5hbWUiOiJjbG91ZHNsaXQifQ.7iUZuCDn1SNn7CxuR_kdAWf9_PfpuJlqPmy7ZdB2x9U" 57 | timeout: 10 58 | retry-count: 100 59 | eth: 60 | url: "https://ropsten.infura.io/v3" 61 | projectid: "45630f96f9d841679dc200a7c97763d2" 62 | -------------------------------------------------------------------------------- /provider/internal/server/eth.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | 7 | "github.com/flowshield/flowshield/provider/internal/config" 8 | 9 | "github.com/flowshield/flowshield/provider/pkg/logger" 10 | 11 | "github.com/ethereum/go-ethereum/accounts/abi/bind" 12 | "github.com/ethereum/go-ethereum/common" 13 | "github.com/ethereum/go-ethereum/crypto" 14 | "github.com/ethereum/go-ethereum/ethclient" 15 | 16 | "github.com/flowshield/flowshield/provider/pkg/contract" 17 | ) 18 | 19 | const Provider = 2 20 | 21 | func runETH() error { 22 | logger.Infof("starting run deposit process...") 23 | ctx := context.Background() 24 | cfg := config.C.Web3 25 | client, err := ethclient.Dial(cfg.EthAddress()) 26 | if err != nil { 27 | return err 28 | } 29 | chanID, err := client.ChainID(ctx) 30 | if err != nil { 31 | return err 32 | } 33 | contractAdd := common.HexToAddress(cfg.Contract.Token) 34 | instance, err := contract.NewSlit(contractAdd, client) 35 | if err != nil { 36 | return err 37 | } 38 | privateKey, err := crypto.HexToECDSA(cfg.PrivateKey) 39 | auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chanID) 40 | if err != nil { 41 | return err 42 | } 43 | logger.Infof("checking if deposited or not...") 44 | isDeposit, err := instance.IsDeposit(&bind.CallOpts{ 45 | From: auth.From, 46 | }, Provider) 47 | if err != nil { 48 | return err 49 | } 50 | if isDeposit { 51 | logger.Infof("you have deposited!") 52 | return nil 53 | } 54 | logger.Infof("you have not deposited! trying to deposit...") 55 | // 尝试质押 56 | tra, err := instance.Stake(auth, Provider) 57 | if err != nil { 58 | return err 59 | } 60 | rec, err := bind.WaitMined(ctx, client, tra) 61 | if err != nil { 62 | return err 63 | } 64 | if rec.Status > 0 { 65 | logger.Infof("deposited succeed") 66 | return nil 67 | } 68 | return errors.New("sorry,deposit failed") 69 | } 70 | -------------------------------------------------------------------------------- /client/internal/logger.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "github.com/flowshield/flowshield/client/internal/config" 5 | "github.com/flowshield/flowshield/client/pkg/logger" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/sirupsen/logrus" 10 | 11 | loggerhook "github.com/flowshield/flowshield/client/pkg/logger/hook" 12 | loggerredishook "github.com/flowshield/flowshield/client/pkg/logger/hook/redis" 13 | ) 14 | 15 | // InitLogger initialize the log module 16 | func InitLogger() (func(), error) { 17 | c := config.C.Log 18 | logger.SetLevel(c.Level) 19 | logger.SetFormatter(c.Format) 20 | 21 | // setting log output 22 | var file *os.File 23 | if c.Output != "" { 24 | switch c.Output { 25 | case "stdout": 26 | logger.SetOutput(os.Stdout) 27 | case "stderr": 28 | logger.SetOutput(os.Stderr) 29 | case "file": 30 | if name := c.OutputFile; name != "" { 31 | _ = os.MkdirAll(filepath.Dir(name), 0o777) 32 | 33 | f, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o666) 34 | if err != nil { 35 | return nil, err 36 | } 37 | logger.SetOutput(f) 38 | file = f 39 | } 40 | } 41 | } 42 | 43 | var hook *loggerhook.Hook 44 | if c.EnableHook { 45 | var hookLevels []logrus.Level 46 | for _, lvl := range c.HookLevels { 47 | plvl, err := logrus.ParseLevel(lvl) 48 | if err != nil { 49 | return nil, err 50 | } 51 | hookLevels = append(hookLevels, plvl) 52 | } 53 | if c.Hook.IsRedis() { 54 | hc := config.C.LogRedisHook 55 | h := loggerhook.New(loggerredishook.New(&loggerredishook.Config{ 56 | Addr: hc.Addr, 57 | Key: hc.Key, 58 | }), 59 | loggerhook.SetMaxWorkers(c.HookMaxThread), 60 | loggerhook.SetMaxQueues(c.HookMaxBuffer), 61 | loggerhook.SetLevels(hookLevels...), 62 | ) 63 | logger.AddHook(h) 64 | hook = h 65 | } 66 | } 67 | 68 | return func() { 69 | if file != nil { 70 | file.Close() 71 | } 72 | 73 | if hook != nil { 74 | hook.Flush() 75 | } 76 | }, nil 77 | } 78 | -------------------------------------------------------------------------------- /provider/internal/server/node.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/flowshield/flowshield/provider/internal/bll" 7 | "github.com/flowshield/flowshield/provider/internal/config" 8 | "github.com/flowshield/flowshield/provider/pkg/logger" 9 | "github.com/flowshield/flowshield/provider/pkg/p2p" 10 | "github.com/flowshield/flowshield/provider/pkg/web3/eth" 11 | "github.com/flowshield/flowshield/provider/pkg/web3/w3s" 12 | "github.com/sirupsen/logrus" 13 | ) 14 | 15 | func InitNode(ctx context.Context) error { 16 | if err := w3s.Init(&config.C.Web3); err != nil { 17 | logger.Errorf("w3s init error : %v", err) 18 | return err 19 | } 20 | if err := eth.Init(&config.C.Web3); err != nil { 21 | logger.Errorf("eth init error : %v", err) 22 | return err 23 | } 24 | if err := runETH(); err != nil { 25 | logger.Errorf("runETH error : %v", err) 26 | return err 27 | } 28 | if config.C.P2p.Enable { 29 | // Create a new P2PHost 30 | logrus.Infoln("use service discovery id:", config.C.P2p.ServiceDiscoveryID) 31 | p2phost := p2p.NewP2P(config.C.P2p.ServiceDiscoveryID) 32 | logrus.Infoln("Completed P2P Setup") 33 | logrus.Infoln("Please wait for about 30 seconds ...") 34 | // Connect to peers with the chosen discovery method 35 | switch config.C.P2p.ServiceDiscoveryMode { 36 | case "announce": 37 | p2phost.AnnounceConnect() 38 | case "advertise": 39 | p2phost.AdvertiseConnect() 40 | default: 41 | p2phost.AdvertiseConnect() 42 | } 43 | logrus.Infoln("Connected to Service Peers") 44 | 45 | // Join the chat room 46 | chatapp, err := p2p.JoinPubSub(p2phost, "server_provider", config.C.P2p.ServiceMetadataTopic) 47 | if err != nil { 48 | logger.Fatalf("Join PubSub Error: %v", err) 49 | } 50 | logrus.Infof("Successfully joined [%s] P2P channel.", config.C.P2p.ServiceMetadataTopic) 51 | psBll := bll.NewPubsub() 52 | go psBll.InitByDB(ctx, chatapp) 53 | go psBll.StartPubsubHandler(ctx, chatapp, p2phost) 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /fullnode/app/v1/access/model/mmysql/client.go: -------------------------------------------------------------------------------- 1 | package mmysql 2 | 3 | import ( 4 | "database/sql/driver" 5 | "encoding/json" 6 | ) 7 | 8 | const ( 9 | WaitingPaid = iota 10 | Paid 11 | Success 12 | ) 13 | 14 | type Client struct { 15 | ID uint `gorm:"primarykey"` 16 | CreatedAt int64 `gorm:"autoCreateTime"` 17 | UpdatedAt int64 `gorm:"autoUpdateTime"` 18 | UserUUID string `json:"user_uuid" gorm:"user_uuid"` 19 | Name string `json:"name"` 20 | PeerID string `json:"peer_id"` 21 | UUID string `json:"uuid" gorm:"column:uuid"` 22 | Port int `json:"port"` 23 | Duration uint `json:"duration"` // 使用时间:小时 24 | Price uint `json:"price"` // 金额 25 | ResourceCid string `json:"resource_cid"` 26 | ServerCid string `json:"server_cid"` 27 | ClientCid string `json:"client_cid"` 28 | Status uint `json:"status"` // 0:待支付,1:已支付,待回调,2:已完成 29 | } 30 | 31 | func (Client) TableName() string { 32 | return "zta_client" 33 | } 34 | 35 | //type Servers ServerAttr 36 | 37 | //type Resource []Resource 38 | 39 | type ClientTarget struct { 40 | Host string `json:"host" binding:"required"` 41 | Port int `json:"port" binding:"required"` 42 | } 43 | 44 | //func (c Resource) Value() (driver.Value, error) { 45 | // b, err := json.Marshal(c) 46 | // return string(b), err 47 | //} 48 | // 49 | //func (c *Resource) Scan(input interface{}) error { 50 | // return json.Unmarshal(input.([]byte), c) 51 | //} 52 | 53 | func (c ClientTarget) Value() (driver.Value, error) { 54 | b, err := json.Marshal(c) 55 | return string(b), err 56 | } 57 | 58 | func (c *ClientTarget) Scan(input interface{}) error { 59 | return json.Unmarshal(input.([]byte), c) 60 | } 61 | 62 | //type ClientAttrs struct { 63 | // Type string `json:"type"` 64 | // Name string `json:"name"` 65 | // UUID string `json:"uuid"` 66 | // Port int `json:"port"` 67 | // //Relay []RelayAttrs `json:"relay"` 68 | // Server ServerAttr `json:"server"` 69 | // Target ClientTarget `json:"target"` 70 | //} 71 | -------------------------------------------------------------------------------- /portal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudslit", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve --mode development --https", 7 | "build": "vue-cli-service build", 8 | "test:unit": "vue-cli-service test:unit", 9 | "test:e2e": "vue-cli-service test:e2e", 10 | "lint": "vue-cli-service lint" 11 | }, 12 | "dependencies": { 13 | "@ceramicnetwork/blockchain-utils-linking": "^2.0.9", 14 | "@ceramicnetwork/http-client": "^2.3.2", 15 | "@glazed/did-datastore": "^0.3.2", 16 | "@glazed/did-session": "^0.1.1", 17 | "axios": "^0.26.1", 18 | "core-js": "^3.8.3", 19 | "ethers": "^5.6.4", 20 | "js-cookie": "^3.0.1", 21 | "node-polyfill-webpack-plugin": "^2.0.0", 22 | "qs": "^6.10.3", 23 | "vue": "^2.6.14", 24 | "vue-clipboard2": "^0.3.3", 25 | "vue-router": "^3.5.1", 26 | "vuetify": "^2.6.0", 27 | "vuex": "^3.6.2", 28 | "web3": "^1.7.4" 29 | }, 30 | "devDependencies": { 31 | "@babel/core": "^7.12.16", 32 | "@babel/eslint-parser": "^7.12.16", 33 | "@vue/cli-plugin-babel": "~5.0.0", 34 | "@vue/cli-plugin-e2e-cypress": "~5.0.0", 35 | "@vue/cli-plugin-eslint": "~5.0.0", 36 | "@vue/cli-plugin-router": "~5.0.0", 37 | "@vue/cli-plugin-unit-jest": "~5.0.0", 38 | "@vue/cli-plugin-vuex": "~5.0.0", 39 | "@vue/cli-service": "~5.0.0", 40 | "@vue/test-utils": "^1.1.3", 41 | "@vue/vue2-jest": "^27.0.0-alpha.2", 42 | "babel-jest": "^27.0.6", 43 | "buffer": "^6.0.3", 44 | "cypress": "^8.3.0", 45 | "dids": "^3.2.0", 46 | "eslint": "^7.32.0", 47 | "eslint-plugin-vue": "^8.0.3", 48 | "jest": "^27.0.5", 49 | "key-did-provider-ed25519": "^2.0.1", 50 | "key-did-resolver": "^2.0.6", 51 | "sass": "^1.32.7", 52 | "sass-loader": "^12.0.0", 53 | "vue-cli-plugin-vuetify": "~2.4.8", 54 | "vue-template-compiler": "^2.6.14", 55 | "vuetify-loader": "^1.7.0", 56 | "webpack": "^5.74.0", 57 | "webpack-cli": "^4.10.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /provider/internal/logger.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/flowshield/flowshield/provider/internal/config" 8 | "github.com/flowshield/flowshield/provider/pkg/logger" 9 | 10 | "github.com/sirupsen/logrus" 11 | 12 | loggerhook "github.com/flowshield/flowshield/provider/pkg/logger/hook" 13 | loggerredishook "github.com/flowshield/flowshield/provider/pkg/logger/hook/redis" 14 | ) 15 | 16 | // InitLogger initialize the log module 17 | func InitLogger() (func(), error) { 18 | c := config.C.Log 19 | logger.SetLevel(c.Level) 20 | logger.SetFormatter(c.Format) 21 | 22 | // setting log output 23 | var file *os.File 24 | if c.Output != "" { 25 | switch c.Output { 26 | case "stdout": 27 | logger.SetOutput(os.Stdout) 28 | case "stderr": 29 | logger.SetOutput(os.Stderr) 30 | case "file": 31 | if name := c.OutputFile; name != "" { 32 | _ = os.MkdirAll(filepath.Dir(name), 0o777) 33 | 34 | f, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o666) 35 | if err != nil { 36 | return nil, err 37 | } 38 | logger.SetOutput(f) 39 | file = f 40 | } 41 | } 42 | } 43 | 44 | var hook *loggerhook.Hook 45 | if c.EnableHook { 46 | var hookLevels []logrus.Level 47 | for _, lvl := range c.HookLevels { 48 | plvl, err := logrus.ParseLevel(lvl) 49 | if err != nil { 50 | return nil, err 51 | } 52 | hookLevels = append(hookLevels, plvl) 53 | } 54 | if c.Hook.IsRedis() { 55 | hc := config.C.LogRedisHook 56 | h := loggerhook.New(loggerredishook.New(&loggerredishook.Config{ 57 | Addr: hc.Addr, 58 | Key: hc.Key, 59 | }), 60 | loggerhook.SetMaxWorkers(c.HookMaxThread), 61 | loggerhook.SetMaxQueues(c.HookMaxBuffer), 62 | loggerhook.SetLevels(hookLevels...), 63 | ) 64 | logger.AddHook(h) 65 | hook = h 66 | } 67 | } 68 | 69 | return func() { 70 | if file != nil { 71 | file.Close() 72 | } 73 | 74 | if hook != nil { 75 | hook.Flush() 76 | } 77 | }, nil 78 | } 79 | -------------------------------------------------------------------------------- /fullnode/pkg/confer/viper.go: -------------------------------------------------------------------------------- 1 | package confer 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "sync" 7 | 8 | "github.com/ethereum/go-ethereum/crypto" 9 | "github.com/spf13/viper" 10 | ) 11 | 12 | var globalConfig *ServerConfig 13 | var mutex sync.RWMutex 14 | 15 | func Init(configURL string) (err error) { 16 | v := viper.New() 17 | v.SetConfigFile(configURL) 18 | err = v.ReadInConfig() 19 | if err != nil { 20 | err = fmt.Errorf("fatal error config file: %w", err) 21 | return 22 | } 23 | if err = v.Unmarshal(&globalConfig); err != nil { 24 | return 25 | } 26 | return handleConfig(globalConfig) 27 | } 28 | 29 | func handleConfig(config *ServerConfig) error { 30 | config.replaceByEnv(&config.Redis.Addr) 31 | config.replaceByEnv(&config.Mysql.Write.Host) 32 | config.replaceByEnv(&config.Mysql.Write.User) 33 | config.replaceByEnv(&config.Mysql.Write.Password) 34 | config.replaceByEnv(&config.CA.SignURL) 35 | config.replaceByEnv(&config.CA.AuthKey) 36 | config.replaceByEnv(&config.Oauth2.ClientID) 37 | config.replaceByEnv(&config.Oauth2.ClientSecret) 38 | config.replaceByEnv(&config.Web3.Register) 39 | config.replaceByEnv(&config.Web3.PrivateKey) 40 | config.replaceByEnv(&config.P2P.ServiceDiscoveryID) 41 | config.replaceByEnv(&config.P2P.ServiceMetadataTopic) 42 | privateKey, err := crypto.HexToECDSA(config.Web3.PrivateKey) 43 | if err != nil { 44 | return err 45 | } 46 | // Account 处理 47 | config.P2P.Account = crypto.PubkeyToAddress(privateKey.PublicKey).String() 48 | config.replaceByEnv(&config.Web3.Contract.Token) 49 | config.replaceByEnv(&config.Web3.W3S.Token) 50 | config.replaceByEnv(&config.Web3.ETH.URL) 51 | config.Mysql.Write.DBName = globalConfig.Mysql.DBName 52 | config.Mysql.Write.Prefix = globalConfig.Mysql.Prefix 53 | return nil 54 | } 55 | 56 | func (*ServerConfig) replaceByEnv(conf *string) { 57 | if s := os.Getenv(*conf); len(s) > 0 { 58 | *conf = s 59 | } 60 | } 61 | 62 | func GlobalConfig() *ServerConfig { 63 | mutex.RLock() 64 | defer mutex.RUnlock() 65 | return globalConfig 66 | } 67 | -------------------------------------------------------------------------------- /provider/configs/config.toml: -------------------------------------------------------------------------------- 1 | # mode(debug,test,release) 2 | RunMode = "release" 3 | 4 | # Whether to print configuration parameters at startup 5 | PrintConfig = true 6 | 7 | # Information about themselves 8 | [App] 9 | # Provide publicly available domain names 10 | LocalAddr = "" 11 | # Provide the public port, which is also the default listening port of the program 12 | LocalPort = 5091 13 | HttpListenAddr = "0.0.0.0:15091" 14 | 15 | # p2p config 16 | [P2p] 17 | Enable = true 18 | ServiceDiscoveryID = "flowshield/provider" 19 | ServiceDiscoveryMode = "advertise" # advertise or announce 20 | ServiceMetadataTopic = "flowshield_provider_metadata" 21 | 22 | [Web3] 23 | # Wallet account private key 24 | PrivateKey = "" 25 | # Price - Price of services provided, unit = CSD/h, CSD It's our token 26 | Price = 1 27 | 28 | [Web3.Contract] 29 | # Contract account 30 | Token = "" 31 | 32 | # wbs3.storage token 33 | [Web3.W3s] 34 | Token = "" 35 | # Request timeout (unit/second) 36 | Timeout = 10 37 | # Request failed retries 38 | RetryCount = 100 39 | 40 | # Ethereum information 41 | [Web3.Eth] 42 | Url = "" 43 | ProjectID = "" 44 | 45 | [MySQL] 46 | # Connection address 47 | Host = "127.0.0.1" 48 | # Connection port 49 | Port= 23306 50 | # user name 51 | User = "root" 52 | # Password 53 | Password = "123456" 54 | # Database 55 | DBName = "provider" 56 | # Prefix 57 | Prefix = "pr_" 58 | # Connection parameters 59 | Parameters = "charset=utf8mb4&parseTime=True&loc=Local&allowNativePasswords=true" 60 | PoolMinCap = 10 61 | PoolExCap = 5 62 | PoolMaxCap = 40 63 | PoolIdleTimeout = 3600 64 | PoolWaitCount = 1000 65 | PoolWaiTimeout = 30 66 | 67 | [Log] 68 | # level(1:fatal,2:error,3:warn,4:info,5:debug,6:trace) 69 | Level = 4 70 | # text、json 71 | Format = "text" 72 | # stdout、stderr、file 73 | Output = "stdout" 74 | OutputFile = "data/logger.log" 75 | EnableHook = false 76 | HookLevels = ["info", "warn", "error"] 77 | # redis 78 | Hook = "redis" 79 | HookMaxThread = 1 80 | HookMaxBuffer = 512 81 | 82 | [LogRedisHook] 83 | Addr = "127.0.0.1:6379" 84 | Key = "log_key" -------------------------------------------------------------------------------- /contract/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "OwnableUpgradeable", 4 | "sourceName": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": false, 11 | "internalType": "uint8", 12 | "name": "version", 13 | "type": "uint8" 14 | } 15 | ], 16 | "name": "Initialized", 17 | "type": "event" 18 | }, 19 | { 20 | "anonymous": false, 21 | "inputs": [ 22 | { 23 | "indexed": true, 24 | "internalType": "address", 25 | "name": "previousOwner", 26 | "type": "address" 27 | }, 28 | { 29 | "indexed": true, 30 | "internalType": "address", 31 | "name": "newOwner", 32 | "type": "address" 33 | } 34 | ], 35 | "name": "OwnershipTransferred", 36 | "type": "event" 37 | }, 38 | { 39 | "inputs": [], 40 | "name": "owner", 41 | "outputs": [ 42 | { 43 | "internalType": "address", 44 | "name": "", 45 | "type": "address" 46 | } 47 | ], 48 | "stateMutability": "view", 49 | "type": "function" 50 | }, 51 | { 52 | "inputs": [], 53 | "name": "renounceOwnership", 54 | "outputs": [], 55 | "stateMutability": "nonpayable", 56 | "type": "function" 57 | }, 58 | { 59 | "inputs": [ 60 | { 61 | "internalType": "address", 62 | "name": "newOwner", 63 | "type": "address" 64 | } 65 | ], 66 | "name": "transferOwnership", 67 | "outputs": [], 68 | "stateMutability": "nonpayable", 69 | "type": "function" 70 | } 71 | ], 72 | "bytecode": "0x", 73 | "deployedBytecode": "0x", 74 | "linkReferences": {}, 75 | "deployedLinkReferences": {} 76 | } 77 | -------------------------------------------------------------------------------- /portal/src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 35 | 48 | 49 | 71 | -------------------------------------------------------------------------------- /client/internal/schema/s_resource.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "net" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | type Resource struct { 10 | UUID string `json:"uuid"` 11 | Name string `json:"name"` 12 | Type string `json:"type"` 13 | Host string `json:"host"` 14 | Port string `json:"port"` 15 | } 16 | 17 | type Resources []*Resource 18 | 19 | // Verify that the access resource exists 20 | func (a Resources) VerifyResources(target Target) bool { 21 | isIP := false 22 | pip := net.ParseIP(target.Host) 23 | if pip != nil { 24 | isIP = true 25 | } 26 | for _, item := range a { 27 | if item.Host == "*" { 28 | return true 29 | } 30 | // dns validation 31 | if item.Type == "dns" && !isIP { 32 | if item.Host == target.Host && 33 | item.CheckPort(target.Port) { 34 | return true 35 | } 36 | if item.CheckPort(target.Port) && strings.Index(item.Host, "*.") == 0 && 37 | (strings.Contains(target.Host, item.Host[1:]) || item.Host[2:] == target.Host) { 38 | return true 39 | } 40 | } 41 | if item.Type == "cidr" && isIP && item.CheckPort(target.Port) { 42 | _, subnet, err := net.ParseCIDR(item.Host) 43 | if err != nil { 44 | // Resource restriction non-CIDR, direct comparison 45 | if target.Host == item.Host { 46 | return true 47 | } 48 | continue // The IP address does not match and is skipped 49 | } 50 | if subnet.Contains(pip) { 51 | return true 52 | } 53 | } 54 | } 55 | return false 56 | } 57 | 58 | // CheckPort Checking the Target Port eg:8080;9090;3000-4000 59 | func (a *Resource) CheckPort(targetPort int) bool { 60 | fPort := strings.Split(a.Port, ";") 61 | for _, item := range fPort { 62 | if item == strconv.Itoa(targetPort) { 63 | return true 64 | } 65 | jPort := strings.Split(a.Port, "-") 66 | if len(jPort) == 2 { 67 | minPortInt, _ := strconv.Atoi(jPort[0]) 68 | maxPortInt, _ := strconv.Atoi(jPort[1]) 69 | if targetPort >= minPortInt && targetPort <= maxPortInt { 70 | return true 71 | } 72 | } else { 73 | continue 74 | } 75 | } 76 | return false 77 | } 78 | -------------------------------------------------------------------------------- /ca/pkg/logger/redis_hook/redis_hook.go: -------------------------------------------------------------------------------- 1 | package redis_hook 2 | 3 | import ( 4 | "fmt" 5 | "github.com/garyburd/redigo/redis" 6 | "time" 7 | ) 8 | 9 | // HookConfig stores configuration needed to setup the hook 10 | type HookConfig struct { 11 | Key string 12 | Host string 13 | Password string 14 | Port int 15 | TTL int 16 | } 17 | 18 | // RedisHook to sends logs to Redis server 19 | type RedisHook struct { 20 | RedisPool *redis.Pool 21 | RedisHost string 22 | RedisKey string 23 | LogstashFormat string 24 | AppName string 25 | Hostname string 26 | RedisPort int 27 | TTL int 28 | } 29 | 30 | // NewHook creates a hook to be added to an instance of logger 31 | func NewHook(config HookConfig) (redisHook *RedisHook, err error) { 32 | pool := newRedisConnectionPool(config.Host, config.Password, config.Port, 0) 33 | 34 | // test if connection with REDIS can be established 35 | conn := pool.Get() 36 | defer conn.Close() 37 | 38 | // check connection 39 | _, err = conn.Do("PING") 40 | if err != nil { 41 | err = fmt.Errorf("unable to connect to REDIS: %s", err) 42 | } 43 | redisHook = &RedisHook{ 44 | RedisHost: config.Host, 45 | RedisPool: pool, 46 | RedisKey: config.Key, 47 | LogstashFormat: "origin", 48 | TTL: config.TTL, 49 | } 50 | return 51 | } 52 | 53 | func newRedisConnectionPool(server, password string, port int, db int) *redis.Pool { 54 | hostPort := fmt.Sprintf("%s:%d", server, port) 55 | return &redis.Pool{ 56 | MaxIdle: 3, 57 | IdleTimeout: 240 * time.Second, 58 | Dial: func() (redis.Conn, error) { 59 | c, err := redis.Dial("tcp", hostPort, redis.DialDatabase(db), 60 | redis.DialPassword(password), 61 | redis.DialConnectTimeout(time.Second), 62 | redis.DialReadTimeout(time.Millisecond*100), 63 | redis.DialWriteTimeout(time.Millisecond*100)) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return c, err 68 | }, 69 | TestOnBorrow: func(c redis.Conn, t time.Time) error { 70 | _, err := c.Do("PING") 71 | return err 72 | }, 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /portal/src/components/pem-dialog.vue: -------------------------------------------------------------------------------- 1 | 34 | 68 | -------------------------------------------------------------------------------- /provider/internal/schema/s_resource.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | type Resource struct { 9 | UUID string `json:"uuid"` 10 | Name string `json:"name"` 11 | Type string `json:"type"` 12 | Host string `json:"host"` 13 | Port string `json:"port"` 14 | } 15 | 16 | type Resources []*Resource 17 | 18 | //// Verify that the access resource exists 19 | //func (a Resources) VerifyResources(target Target) bool { 20 | // isIP := false 21 | // pip := net.ParseIP(target.Host) 22 | // if pip != nil { 23 | // isIP = true 24 | // } 25 | // for _, item := range a { 26 | // if item.Host == "*" { 27 | // return true 28 | // } 29 | // // dns validation 30 | // if item.Type == "dns" && !isIP { 31 | // if item.Host == target.Host && 32 | // item.CheckPort(target.Port) { 33 | // return true 34 | // } 35 | // if item.CheckPort(target.Port) && strings.Index(item.Host, "*.") == 0 && 36 | // (strings.Contains(target.Host, item.Host[1:]) || item.Host[2:] == target.Host) { 37 | // return true 38 | // } 39 | // } 40 | // if item.Type == "cidr" && isIP && item.CheckPort(target.Port) { 41 | // _, subnet, err := net.ParseCIDR(item.Host) 42 | // if err != nil { 43 | // // Resource restriction non-CIDR, direct comparison 44 | // if target.Host == item.Host { 45 | // return true 46 | // } 47 | // continue // The IP address does not match and is skipped 48 | // } 49 | // if subnet.Contains(pip) { 50 | // return true 51 | // } 52 | // } 53 | // } 54 | // return false 55 | //} 56 | 57 | // CheckPort Checking the Target Port eg:8080;9090;3000-4000 58 | func (a *Resource) CheckPort(targetPort int) bool { 59 | fPort := strings.Split(a.Port, ";") 60 | for _, item := range fPort { 61 | if item == strconv.Itoa(targetPort) { 62 | return true 63 | } 64 | jPort := strings.Split(a.Port, "-") 65 | if len(jPort) == 2 { 66 | minPortInt, _ := strconv.Atoi(jPort[0]) 67 | maxPortInt, _ := strconv.Atoi(jPort[1]) 68 | if targetPort >= minPortInt && targetPort <= maxPortInt { 69 | return true 70 | } 71 | } else { 72 | continue 73 | } 74 | } 75 | return false 76 | } 77 | -------------------------------------------------------------------------------- /client/pkg/certificate/verify.go: -------------------------------------------------------------------------------- 1 | package certificate 2 | 3 | import ( 4 | "crypto/x509" 5 | "encoding/pem" 6 | "errors" 7 | ) 8 | 9 | type verifyCert struct { 10 | leaf string 11 | intermediates []string 12 | roots []string 13 | dnsName string 14 | } 15 | 16 | // NewVerify Create a certificate validator 17 | func NewVerify(cert, rootCert, dnsName string) *verifyCert { 18 | return &verifyCert{ 19 | leaf: cert, 20 | roots: []string{rootCert}, 21 | dnsName: dnsName, 22 | } 23 | } 24 | 25 | // expectAuthorityUnknown error handling 26 | func (a *verifyCert) expectAuthorityUnknown(err error) error { 27 | e, ok := err.(x509.UnknownAuthorityError) 28 | if !ok { 29 | return errors.New("error was not UnknownAuthorityError: " + err.Error()) 30 | } 31 | if e.Cert == nil { 32 | return errors.New("error was UnknownAuthorityError, but missing Cert: " + err.Error()) 33 | } 34 | return err 35 | } 36 | 37 | // certificateFromPEM analytical certificate 38 | func (a *verifyCert) certificateFromPEM(pemBytes string) (*x509.Certificate, error) { 39 | block, _ := pem.Decode([]byte(pemBytes)) 40 | if block == nil { 41 | return nil, errors.New("failed to decode PEM") 42 | } 43 | return x509.ParseCertificate(block.Bytes) 44 | } 45 | 46 | func (a *verifyCert) Verify() error { 47 | opts := x509.VerifyOptions{ 48 | Intermediates: x509.NewCertPool(), 49 | DNSName: a.dnsName, 50 | } 51 | opts.Roots = x509.NewCertPool() 52 | for j, root := range a.roots { 53 | ok := opts.Roots.AppendCertsFromPEM([]byte(root)) 54 | if !ok { 55 | return errors.New("failed to parse root #" + string(rune(j))) 56 | } 57 | } 58 | 59 | for j, intermediate := range a.intermediates { 60 | ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate)) 61 | if !ok { 62 | return errors.New("failed to parse intermediate #" + string(rune(j))) 63 | } 64 | } 65 | 66 | leaf, err := a.certificateFromPEM(a.leaf) 67 | if err != nil { 68 | return errors.New("failed to parse leaf:" + err.Error()) 69 | } 70 | 71 | _, err = leaf.Verify(opts) 72 | if err != nil { 73 | return a.expectAuthorityUnknown(err) 74 | } 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /provider/pkg/certificate/verify.go: -------------------------------------------------------------------------------- 1 | package certificate 2 | 3 | import ( 4 | "crypto/x509" 5 | "encoding/pem" 6 | "errors" 7 | ) 8 | 9 | type verifyCert struct { 10 | leaf string 11 | intermediates []string 12 | roots []string 13 | dnsName string 14 | } 15 | 16 | // NewVerify Create a certificate validator 17 | func NewVerify(cert, rootCert, dnsName string) *verifyCert { 18 | return &verifyCert{ 19 | leaf: cert, 20 | roots: []string{rootCert}, 21 | dnsName: dnsName, 22 | } 23 | } 24 | 25 | // expectAuthorityUnknown error handling 26 | func (a *verifyCert) expectAuthorityUnknown(err error) error { 27 | e, ok := err.(x509.UnknownAuthorityError) 28 | if !ok { 29 | return errors.New("error was not UnknownAuthorityError: " + err.Error()) 30 | } 31 | if e.Cert == nil { 32 | return errors.New("error was UnknownAuthorityError, but missing Cert: " + err.Error()) 33 | } 34 | return err 35 | } 36 | 37 | // certificateFromPEM analytical certificate 38 | func (a *verifyCert) certificateFromPEM(pemBytes string) (*x509.Certificate, error) { 39 | block, _ := pem.Decode([]byte(pemBytes)) 40 | if block == nil { 41 | return nil, errors.New("failed to decode PEM") 42 | } 43 | return x509.ParseCertificate(block.Bytes) 44 | } 45 | 46 | func (a *verifyCert) Verify() error { 47 | opts := x509.VerifyOptions{ 48 | Intermediates: x509.NewCertPool(), 49 | DNSName: a.dnsName, 50 | } 51 | opts.Roots = x509.NewCertPool() 52 | for j, root := range a.roots { 53 | ok := opts.Roots.AppendCertsFromPEM([]byte(root)) 54 | if !ok { 55 | return errors.New("failed to parse root #" + string(rune(j))) 56 | } 57 | } 58 | 59 | for j, intermediate := range a.intermediates { 60 | ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate)) 61 | if !ok { 62 | return errors.New("failed to parse intermediate #" + string(rune(j))) 63 | } 64 | } 65 | 66 | leaf, err := a.certificateFromPEM(a.leaf) 67 | if err != nil { 68 | return errors.New("failed to parse leaf:" + err.Error()) 69 | } 70 | 71 | _, err = leaf.Verify(opts) 72 | if err != nil { 73 | return a.expectAuthorityUnknown(err) 74 | } 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /verifier/pkg/gin/gin.go: -------------------------------------------------------------------------------- 1 | package gin 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "log" 7 | "net/http" 8 | "os" 9 | "os/signal" 10 | "sync" 11 | "time" 12 | 13 | "github.com/flowshield/flowshield/verifier/pkg/confer" 14 | "github.com/gin-gonic/gin" 15 | ) 16 | 17 | type OnShutdownF struct { 18 | f func(cancel context.CancelFunc) 19 | timeout time.Duration 20 | } 21 | 22 | var ( 23 | onShutdown []OnShutdownF 24 | ) 25 | 26 | func RegisterOnShutdown(f func(cancel context.CancelFunc), timeout time.Duration) { 27 | onShutdown = append(onShutdown, OnShutdownF{ 28 | f: f, 29 | timeout: timeout, 30 | }) 31 | } 32 | 33 | func NewGin() *gin.Engine { 34 | if confer.ConfigEnvIsDev() { 35 | gin.SetMode(gin.DebugMode) 36 | } else { 37 | gin.SetMode(gin.ReleaseMode) 38 | } 39 | r := gin.New() 40 | r.Use(gin.Recovery()) 41 | if confer.ConfigEnvIsDev() { 42 | r.Use(gin.Logger()) 43 | } 44 | return r 45 | } 46 | 47 | func ListenHTTP(httpPort string, r http.Handler, timeout int, f ...func()) { 48 | srv := &http.Server{ 49 | Addr: httpPort, 50 | Handler: r, 51 | } 52 | // 监听端口 53 | go func() { 54 | if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { 55 | log.Fatalf("listen: %s\n", err) 56 | } 57 | }() 58 | // 注册关闭使用函数 59 | for _, v := range f { 60 | srv.RegisterOnShutdown(v) 61 | } 62 | // 监听信号 63 | quit := make(chan os.Signal, 1) 64 | signal.Notify(quit, os.Interrupt, os.Kill) 65 | <-quit 66 | // 执行on shutdown 函数 - 同步 67 | for _, v := range onShutdown { 68 | var wg sync.WaitGroup 69 | wg.Add(1) 70 | ctx, cancel := context.WithCancel(context.TODO()) 71 | go v.f(cancel) 72 | select { 73 | case <-time.After(v.timeout): 74 | log.Println("on shutdown timeout:", f) 75 | wg.Done() 76 | case <-ctx.Done(): 77 | wg.Done() 78 | } 79 | wg.Wait() 80 | } 81 | // 执行shutdown 82 | log.Println("Shutdown Server ...") 83 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) 84 | defer cancel() 85 | if err := srv.Shutdown(ctx); err != nil { 86 | log.Panic("Server Shutdown:", err) 87 | } 88 | log.Println("Server exiting") 89 | } 90 | -------------------------------------------------------------------------------- /ca/pkg/signature/util.go: -------------------------------------------------------------------------------- 1 | package signature 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/rand" 6 | "crypto/sha256" 7 | "encoding/hex" 8 | "math/big" 9 | "strings" 10 | 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | // EcdsaSign The encryption result of the text signature is returned. The result is the serialization and splicing of the digital certificate R and s, and then converted into string with hex 15 | func EcdsaSign(priv *ecdsa.PrivateKey, text []byte) (string, error) { 16 | hash := sha256.Sum256(text) 17 | r, s, err := ecdsa.Sign(rand.Reader, priv, hash[:]) 18 | if err != nil { 19 | return "", err 20 | } 21 | return EcdsaSignEncode(r, s) 22 | } 23 | 24 | // EcdsaSignEncode r, s Convert to string 25 | func EcdsaSignEncode(r, s *big.Int) (string, error) { 26 | rt, err := r.MarshalText() 27 | if err != nil { 28 | return "", err 29 | } 30 | st, err := s.MarshalText() 31 | if err != nil { 32 | return "", err 33 | } 34 | b := string(rt) + "," + string(st) 35 | return hex.EncodeToString([]byte(b)), nil 36 | } 37 | 38 | // EcdsaSignDecode r, s String parsing 39 | func EcdsaSignDecode(sign string) (rint, sint big.Int, err error) { 40 | b, err := hex.DecodeString(sign) 41 | if err != nil { 42 | err = errors.New("decrypt error," + err.Error()) 43 | return 44 | } 45 | rs := strings.Split(string(b), ",") 46 | if len(rs) != 2 { 47 | err = errors.New("decode fail") 48 | return 49 | } 50 | err = rint.UnmarshalText([]byte(rs[0])) 51 | if err != nil { 52 | err = errors.New("decrypt rint fail, " + err.Error()) 53 | return 54 | } 55 | err = sint.UnmarshalText([]byte(rs[1])) 56 | if err != nil { 57 | err = errors.New("decrypt sint fail, " + err.Error()) 58 | return 59 | } 60 | return 61 | } 62 | 63 | // EcdsaVerify Verify whether the text content is consistent with the signature. Use the public key to verify the signature and text content 64 | func EcdsaVerify(text []byte, sign string, pubKey *ecdsa.PublicKey) (bool, error) { 65 | hash := sha256.Sum256(text) 66 | rint, sint, err := EcdsaSignDecode(sign) 67 | if err != nil { 68 | return false, err 69 | } 70 | result := ecdsa.Verify(pubKey, hash[:], &rint, &sint) 71 | return result, nil 72 | } 73 | -------------------------------------------------------------------------------- /verifier/pkg/mysql/mysql.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "os" 8 | "time" 9 | 10 | "github.com/flowshield/flowshield/verifier/pkg/confer" 11 | 12 | "github.com/gin-gonic/gin" 13 | "gorm.io/driver/mysql" 14 | "gorm.io/gorm" 15 | glogger "gorm.io/gorm/logger" 16 | "gorm.io/gorm/schema" 17 | ) 18 | 19 | var gormDB *gorm.DB 20 | 21 | type DaoMysql struct { 22 | db *gorm.DB 23 | } 24 | 25 | func NewDaoMysql() *DaoMysql { 26 | return &DaoMysql{ 27 | db: gormDB, 28 | } 29 | } 30 | 31 | func (dao *DaoMysql) Orm(c *gin.Context) *gorm.DB { 32 | if c == nil { 33 | return dao.db 34 | } 35 | return dao.db.WithContext(c.Request.Context()) 36 | } 37 | 38 | func Init(cfg *confer.Mysql) error { 39 | dbConfig := cfg.Write 40 | dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4,utf8&parseTime=True&loc=Local", dbConfig.User, 41 | dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.DBName) 42 | config := &gorm.Config{ 43 | SkipDefaultTransaction: true, 44 | NamingStrategy: schema.NamingStrategy{ 45 | TablePrefix: cfg.Prefix, // 表名前缀,`User`表为`t_users` 46 | SingularTable: true, // 使用单数表名,启用该选项后,`User` 表将是`user` 47 | }, 48 | } 49 | if confer.ConfigEnvIsDev() { 50 | newLogger := glogger.New( 51 | log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer 52 | glogger.Config{ 53 | SlowThreshold: time.Second, // 慢 SQL 阈值 54 | LogLevel: glogger.Info, // Log level 55 | Colorful: true, // 禁用彩色打印 56 | }, 57 | ) 58 | config.Logger = newLogger 59 | } else { 60 | config.Logger = glogger.Default.LogMode(glogger.Silent) 61 | } 62 | db, err := gorm.Open(mysql.Open(dsn), config) 63 | if err != nil { 64 | return err 65 | } 66 | sqlDB, err := db.DB() 67 | if err != nil { 68 | err = errors.New(fmt.Sprintf("initMysql,error: %v", err)) 69 | return err 70 | } 71 | sqlDB.SetMaxIdleConns(cfg.Pool.PoolMinCap) // 空闲链接 72 | sqlDB.SetMaxOpenConns(cfg.Pool.PoolMaxCap) // 最大链接 73 | sqlDB.SetConnMaxLifetime(time.Duration(cfg.Pool.PoolIdleTimeout) * time.Second) // 最大空闲时间 74 | gormDB = db 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /ca/core/config/types.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | cfssl_config "github.com/flowshield/cfssl/config" 5 | ) 6 | 7 | const ( 8 | MetricsTablePrefix = "ca_" 9 | ) 10 | 11 | type IConfig struct { 12 | Log Log `yaml:"log"` 13 | Keymanager Keymanager `yaml:"keymanager"` 14 | Singleca Singleca `yaml:"singleca"` 15 | OCSPHost string `yaml:"ocsp-host"` 16 | HTTP HTTP `yaml:"http"` 17 | SwaggerEnabled bool `yaml:"swagger-enabled"` 18 | Debug bool `yaml:"debug"` 19 | Version string `yaml:"version"` 20 | Hostname string `yaml:"hostname"` 21 | Ocsp Ocsp `yaml:"ocsp"` 22 | } 23 | 24 | type Registry struct { 25 | SelfName string `yaml:"self-name"` 26 | Command string `yaml:"command"` 27 | } 28 | 29 | // ocsp 30 | type Ocsp struct { 31 | CacheTime int `yaml:"cache-time"` 32 | } 33 | 34 | type LogProxy struct { 35 | Host string `yaml:"host"` 36 | Port int `yaml:"port"` 37 | Key string `yaml:"key"` 38 | } 39 | type Log struct { 40 | LogProxy LogProxy `yaml:"log-proxy"` 41 | } 42 | type Singleca struct { 43 | ConfigPath string `yaml:"config-path"` 44 | 45 | // Raw 46 | CfsslConfig *cfssl_config.Config 47 | } 48 | type HTTP struct { 49 | OcspListen string `yaml:"ocsp-listen"` 50 | CaListen string `yaml:"ca-listen"` 51 | Listen string `yaml:"listen"` 52 | } 53 | type Mysql struct { 54 | Dsn string `yaml:"dsn"` 55 | } 56 | type RootCa struct { 57 | O string `yaml:"o"` 58 | Expiry string `yaml:"expiry"` 59 | } 60 | type IntermediateCa struct { 61 | O string `yaml:"o"` 62 | Ou string `yaml:"ou"` 63 | Expiry string `yaml:"expiry"` 64 | } 65 | type CsrTemplates struct { 66 | RootCa RootCa `yaml:"root-ca"` 67 | IntermediateCa IntermediateCa `yaml:"intermediate-ca"` 68 | } 69 | type Keymanager struct { 70 | UpperCa []string `yaml:"upper-ca"` 71 | SelfSign bool `yaml:"self-sign"` 72 | CsrTemplates CsrTemplates `yaml:"csr-templates"` 73 | } 74 | type Vault struct { 75 | Enabled bool `yaml:"enabled"` 76 | Addr string `yaml:"addr"` 77 | Token string `yaml:"token"` 78 | Prefix string `yaml:"prefix"` 79 | } 80 | --------------------------------------------------------------------------------