From 8c61408db7cd63227cfe161967e3b70f90b9fde3 Mon Sep 17 00:00:00 2001 From: Acha Bill <57879913+acha-bill@users.noreply.github.com> Date: Fri, 31 May 2024 15:38:10 +0100 Subject: [PATCH] feat: remove auth (#4679) --- .github/workflows/beekeeper.yml | 3 - cmd/bee/cmd/bcrypt.go | 73 ------- cmd/bee/cmd/cmd.go | 10 - cmd/bee/cmd/start.go | 3 - cmd/bee/cmd/start_dev.go | 6 - go.mod | 3 - go.sum | 7 - openapi/Swarm.yaml | 101 +--------- pkg/api/api.go | 120 +----------- pkg/api/api_test.go | 17 +- pkg/api/auth_test.go | 116 ----------- pkg/api/export_test.go | 2 - pkg/api/router.go | 25 +-- pkg/auth/auth.go | 335 -------------------------------- pkg/auth/auth_test.go | 154 --------------- pkg/auth/handler.go | 56 ------ pkg/auth/main_test.go | 15 -- pkg/auth/mock/auth.go | 35 ---- pkg/node/devnode.go | 16 +- pkg/node/node.go | 17 +- 20 files changed, 8 insertions(+), 1106 deletions(-) delete mode 100644 cmd/bee/cmd/bcrypt.go delete mode 100644 pkg/api/auth_test.go delete mode 100644 pkg/auth/auth.go delete mode 100644 pkg/auth/auth_test.go delete mode 100644 pkg/auth/handler.go delete mode 100644 pkg/auth/main_test.go delete mode 100644 pkg/auth/mock/auth.go diff --git a/.github/workflows/beekeeper.yml b/.github/workflows/beekeeper.yml index 17117b83cc4..71c069a2366 100644 --- a/.github/workflows/beekeeper.yml +++ b/.github/workflows/beekeeper.yml @@ -154,9 +154,6 @@ jobs: - name: Test manifest id: manifest run: timeout ${TIMEOUT} beekeeper check --cluster-name local-dns --checks=ci-manifest - - name: Test authenticate - id: authenticate - run: timeout ${TIMEOUT} bash -c 'until beekeeper check --cluster-name local-dns --checks ci-authenticate; do echo "waiting for auth..."; sleep .3; done' - name: Test postage stamps id: postage-stamps run: timeout ${TIMEOUT} beekeeper check --cluster-name local-dns --checks ci-postage diff --git a/cmd/bee/cmd/bcrypt.go b/cmd/bee/cmd/bcrypt.go deleted file mode 100644 index 94c48a86d37..00000000000 --- a/cmd/bee/cmd/bcrypt.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2022 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmd - -import ( - "errors" - "fmt" - - "github.com/spf13/cobra" - "golang.org/x/crypto/bcrypt" -) - -func (c *command) initHasherCmd() (err error) { - cmd := &cobra.Command{ - Use: "bcrypt", - Short: "Generate or validate a bcrypt hash", - Long: `Generate or validate a bcrypt hash - -Takes a single plain text argument in order to generate a bcrypt hash. -If '--check' flag is provided it will validate the first (plain text) argument against -the second one, which is expected to be a quoted bcrypt hash.`, - Example: ` -$> bee bcrypt super$ecret -$2a$10$eZP5YuhJq2k8DFmj9UJGWOIjDtXu6NcAQMrz7Zj1bgIVBcHA3bU5u - -$> bee bcrypt --check super$ecret '$2a$10$eZP5YuhJq2k8DFmj9UJGWOIjDtXu6NcAQMrz7Zj1bgIVBcHA3bU5u' -OK: password hash matches provided plain text`, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 || len(args) > 2 { - return cmd.Help() - } - - isCheck := c.config.GetBool("check") - - if isCheck { - if len(args) != 2 { - fmt.Println("Usage:", "bee bcrypt", "--check", "your-plain-text-password", "'password-hash'") - return nil - } - - err := bcrypt.CompareHashAndPassword([]byte(args[1]), []byte(args[0])) - if err != nil { - return errors.New("password hash does not match provided plain text") - } - - fmt.Println("OK: password hash matches provided plain text") - return nil - } - - if len(args) != 1 { - return cmd.Help() - } - - hashed, err := bcrypt.GenerateFromPassword([]byte(args[0]), bcrypt.DefaultCost) - if err != nil { - return errors.New("failed to generate password hash") - } - - fmt.Print(string(hashed)) - return nil - }, - PreRunE: func(cmd *cobra.Command, args []string) error { - return c.config.BindPFlags(cmd.Flags()) - }, - } - - cmd.Flags().Bool("check", false, "validate existing hash") - - c.root.AddCommand(cmd) - return nil -} diff --git a/cmd/bee/cmd/cmd.go b/cmd/bee/cmd/cmd.go index 964bb0754c1..f6028e878ec 100644 --- a/cmd/bee/cmd/cmd.go +++ b/cmd/bee/cmd/cmd.go @@ -76,9 +76,6 @@ const ( optionNameStaticNodes = "static-nodes" optionNameAllowPrivateCIDRs = "allow-private-cidrs" optionNameSleepAfter = "sleep-after" - optionNameRestrictedAPI = "restricted" - optionNameTokenEncryptionKey = "token-encryption-key" - optionNameAdminPasswordHash = "admin-password" optionNameUsePostageSnapshot = "use-postage-snapshot" optionNameStorageIncentivesEnable = "storage-incentives-enable" optionNameStateStoreCacheCapacity = "statestore-cache-capacity" @@ -142,10 +139,6 @@ func newCommand(opts ...option) (c *command, err error) { return nil, err } - if err := c.initHasherCmd(); err != nil { - return nil, err - } - if err := c.initInitCmd(); err != nil { return nil, err } @@ -293,9 +286,6 @@ func (c *command) setAllFlags(cmd *cobra.Command) { cmd.Flags().Bool(optionNamePProfMutex, false, "enable pprof mutex profile") cmd.Flags().StringSlice(optionNameStaticNodes, []string{}, "protect nodes from getting kicked out on bootnode") cmd.Flags().Bool(optionNameAllowPrivateCIDRs, false, "allow to advertise private CIDRs to the public network") - cmd.Flags().Bool(optionNameRestrictedAPI, false, "enable permission check on the http APIs") - cmd.Flags().String(optionNameTokenEncryptionKey, "", "admin username to get the security token") - cmd.Flags().String(optionNameAdminPasswordHash, "", "bcrypt hash of the admin password to get the security token") cmd.Flags().Bool(optionNameUsePostageSnapshot, false, "bootstrap node using postage snapshot from the network") cmd.Flags().Bool(optionNameStorageIncentivesEnable, true, "enable storage incentives feature") cmd.Flags().Uint64(optionNameStateStoreCacheCapacity, 100_000, "lru memory caching capacity in number of statestore entries") diff --git a/cmd/bee/cmd/start.go b/cmd/bee/cmd/start.go index d69be019c05..56dda6a2591 100644 --- a/cmd/bee/cmd/start.go +++ b/cmd/bee/cmd/start.go @@ -331,9 +331,6 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo MutexProfile: c.config.GetBool(optionNamePProfMutex), StaticNodes: staticNodes, AllowPrivateCIDRs: c.config.GetBool(optionNameAllowPrivateCIDRs), - Restricted: c.config.GetBool(optionNameRestrictedAPI), - TokenEncryptionKey: c.config.GetString(optionNameTokenEncryptionKey), - AdminPasswordHash: c.config.GetString(optionNameAdminPasswordHash), UsePostageSnapshot: c.config.GetBool(optionNameUsePostageSnapshot), EnableStorageIncentives: c.config.GetBool(optionNameStorageIncentivesEnable), StatestoreCacheCapacity: c.config.GetUint64(optionNameStateStoreCacheCapacity), diff --git a/cmd/bee/cmd/start_dev.go b/cmd/bee/cmd/start_dev.go index 189363a455d..c53158daeaa 100644 --- a/cmd/bee/cmd/start_dev.go +++ b/cmd/bee/cmd/start_dev.go @@ -67,9 +67,6 @@ func (c *command) initStartDevCmd() (err error) { DBDisableSeeksCompaction: c.config.GetBool(optionNameDBDisableSeeksCompaction), CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins), ReserveCapacity: c.config.GetUint64(optionNameDevReserveCapacity), - Restricted: c.config.GetBool(optionNameRestrictedAPI), - TokenEncryptionKey: c.config.GetString(optionNameTokenEncryptionKey), - AdminPasswordHash: c.config.GetString(optionNameAdminPasswordHash), }) if err != nil { return err @@ -142,9 +139,6 @@ func (c *command) initStartDevCmd() (err error) { cmd.Flags().Uint64(optionNameDBBlockCacheCapacity, 32*1024*1024, "size of block cache of the database in bytes") cmd.Flags().Uint64(optionNameDBWriteBufferSize, 32*1024*1024, "size of the database write buffer in bytes") cmd.Flags().Bool(optionNameDBDisableSeeksCompaction, false, "disables db compactions triggered by seeks") - cmd.Flags().Bool(optionNameRestrictedAPI, false, "enable permission check on the http APIs") - cmd.Flags().String(optionNameTokenEncryptionKey, "", "security token encryption hash") - cmd.Flags().String(optionNameAdminPasswordHash, "$2a$10$Maw2HUQjcUINtqdnasOs1ee5MtQl7jxnkv2GqCGfbytAiCElzcbYC", "bcrypt hash of the admin password to get the security token") c.root.AddCommand(cmd) return nil diff --git a/go.mod b/go.mod index 705c161b9f3..da46b1d2016 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( contrib.go.opencensus.io/exporter/prometheus v0.4.2 github.com/armon/go-radix v1.0.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 - github.com/casbin/casbin/v2 v2.35.0 github.com/coreos/go-semver v0.3.0 github.com/ethereum/go-ethereum v1.14.3 github.com/ethersphere/go-price-oracle-abi v0.2.0 @@ -60,7 +59,6 @@ require ( require ( github.com/BurntSushi/toml v1.1.0 // indirect - github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect @@ -92,7 +90,6 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect diff --git a/go.sum b/go.sum index 2e18ee9e929..956c674a405 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,6 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/HdrHistogram/hdrhistogram-go v0.0.0-20200919145931-8dac23c8dac1 h1:nEjGZtKHMK92888VT6XkzKwyiW14v5FFRGeWq2uV7N0= github.com/HdrHistogram/hdrhistogram-go v0.0.0-20200919145931-8dac23c8dac1/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -140,8 +138,6 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= -github.com/casbin/casbin/v2 v2.35.0 h1:f0prVg9LgTJTihjAxWEZhfJptXvah1GpZh12sb5KXNA= -github.com/casbin/casbin/v2 v2.35.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= @@ -336,8 +332,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1285,7 +1279,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= diff --git a/openapi/Swarm.yaml b/openapi/Swarm.yaml index 7bcd224a7d0..2ef77a999ef 100644 --- a/openapi/Swarm.yaml +++ b/openapi/Swarm.yaml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: - version: 6.0.0 + version: 7.0.0 title: Bee API description: "A list of the currently provided Interfaces to interact with the swarm, implementing file operations and sending messages" @@ -31,64 +31,6 @@ servers: description: Service port provided in bee node config paths: - "/auth": - post: - summary: "Authenticate - This endpoint is experimental" - tags: - - Auth - security: - - basicAuth: [ ] - requestBody: - required: true - content: - application/json: - schema: - $ref: "SwarmCommon.yaml#/components/schemas/SecurityTokenRequest" - responses: - "201": - description: Ok - content: - application/json: - schema: - $ref: "SwarmCommon.yaml#/components/schemas/SecurityTokenResponse" - "400": - $ref: "SwarmCommon.yaml#/components/responses/400" - "401": - $ref: "SwarmCommon.yaml#/components/responses/401" - "500": - $ref: "SwarmCommon.yaml#/components/responses/500" - default: - description: Default response - - "/refresh": - post: - summary: "Refresh the auth token - This endpoint is experimental" - tags: - - Auth - security: - - bearerAuth: [ ] - requestBody: - required: true - content: - application/json: - schema: - $ref: "SwarmCommon.yaml#/components/schemas/SecurityTokenRequest" - responses: - "201": - description: Ok - content: - application/json: - schema: - $ref: "SwarmCommon.yaml#/components/schemas/SecurityTokenResponse" - "400": - $ref: "SwarmCommon.yaml#/components/responses/400" - "401": - $ref: "SwarmCommon.yaml#/components/responses/401" - "500": - $ref: "SwarmCommon.yaml#/components/responses/500" - default: - description: Default response - "/bytes": post: summary: "Upload data" @@ -930,7 +872,6 @@ paths: "/addresses": get: summary: Get overlay and underlay addresses of the node - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. tags: - Connectivity responses: @@ -982,7 +923,6 @@ paths: "/balances": get: summary: Get the balances with all known peers including prepaid services - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1002,7 +942,6 @@ paths: "/balances/{address}": get: summary: Get the balances with a specific peer including prepaid services - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1031,7 +970,6 @@ paths: "/blocklist": get: summary: Get a list of blocklisted peers - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1051,7 +989,6 @@ paths: "/consumed": get: summary: Get the past due consumption balances with all known peers - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1071,7 +1008,6 @@ paths: "/consumed/{address}": get: summary: Get the past due consumption balance with a specific peer - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1100,7 +1036,6 @@ paths: "/chequebook/address": get: summary: Get the address of the chequebook contract used - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1116,7 +1051,6 @@ paths: "/chequebook/balance": get: summary: Get the balance of the chequebook - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1190,7 +1124,6 @@ paths: "/connect/{multiAddress}": post: summary: Connect to address - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1220,7 +1153,6 @@ paths: "/reservestate": get: summary: Get reserve state - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1238,7 +1170,6 @@ paths: "/chainstate": get: summary: Get chain state - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1256,7 +1187,6 @@ paths: "/node": get: summary: Get information about the node - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. tags: - Status responses: @@ -1272,7 +1202,6 @@ paths: "/peers": get: summary: Get a list of peers - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1290,7 +1219,6 @@ paths: "/peers/{address}": delete: summary: Remove peer - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1319,7 +1247,6 @@ paths: "/pingpong/{address}": post: summary: Try connection to node - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1350,7 +1277,6 @@ paths: "/settlements/{address}": get: summary: Get amount of sent and received from settlements with a peer - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1379,7 +1305,6 @@ paths: "/settlements": get: summary: Get settlements with all known peers and total amount sent or received - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1399,7 +1324,6 @@ paths: "/timesettlements": get: summary: Get time based settlements with all known peers and total amount sent or received - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1419,7 +1343,6 @@ paths: "/topology": get: summary: Get topology of known network - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1435,7 +1358,6 @@ paths: "/welcome-message": get: summary: Get configured P2P welcome message - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1453,7 +1375,6 @@ paths: description: Default response post: summary: Set P2P welcome message - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1480,7 +1401,6 @@ paths: "/chequebook/cashout/{peer-id}": get: summary: Get last cashout action for the peer - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] parameters: @@ -1507,7 +1427,6 @@ paths: description: Default response post: summary: Cashout the last cheque for the peer - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] parameters: @@ -1540,7 +1459,6 @@ paths: "/chequebook/cheque/{peer-id}": get: summary: Get last cheques for the peer - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] parameters: @@ -1569,7 +1487,6 @@ paths: "/chequebook/cheque": get: summary: Get last cheques for all peers - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1591,7 +1508,6 @@ paths: "/chequebook/deposit": post: summary: Deposit tokens from overlay address into chequebook - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] parameters: @@ -1621,7 +1537,6 @@ paths: "/chequebook/withdraw": post: summary: Withdraw tokens from the chequebook to the overlay address - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] parameters: @@ -1651,7 +1566,6 @@ paths: "/transactions": get: summary: Get list of pending transactions - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. tags: - Transaction responses: @@ -1669,7 +1583,6 @@ paths: "/transactions/{txHash}": get: summary: Get information about a sent transaction - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. parameters: - in: path name: txHash @@ -1694,7 +1607,6 @@ paths: description: Default response post: summary: Rebroadcast existing transaction - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. parameters: - in: path name: txHash @@ -1719,7 +1631,6 @@ paths: description: Default response delete: summary: Cancel existing transaction - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. parameters: - in: path name: txHash @@ -1747,7 +1658,6 @@ paths: "/stamps": get: summary: Get stamps for this node - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1775,7 +1685,6 @@ paths: description: Swarm address of the stamp get: summary: Get an individual postage batch status - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1804,7 +1713,6 @@ paths: description: Swarm address of the stamp get: summary: Get extended bucket data of a batch - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: @@ -1830,8 +1738,6 @@ paths: - bearerAuth: [ ] description: | Be aware, this endpoint creates an on-chain transactions and transfers BZZ from the node's Ethereum account and hence directly manipulates the wallet balance! - - This endpoint can be restricted if the node is spawned with the `--restricted` flag. tags: - Postage Stamps parameters: @@ -1881,8 +1787,6 @@ paths: summary: Top up an existing postage batch. description: | Be aware, this endpoint creates on-chain transactions and transfers BZZ from the node's Ethereum account and hence directly manipulates the wallet balance! - - This endpoint can be restricted if the node is spawned with the `--restricted` flag. tags: - Postage Stamps parameters: @@ -1923,8 +1827,6 @@ paths: summary: Dilute an existing postage batch. description: | Be aware, this endpoint creates on-chain transactions and transfers BZZ from the node's Ethereum account and hence directly manipulates the wallet balance! - - This endpoint can be restricted if the node is spawned with the `--restricted` flag. tags: - Postage Stamps parameters: @@ -1961,7 +1863,6 @@ paths: "/batches": get: summary: Get all globally available batches that were purchased by all nodes. - description: This endpoint can be restricted if the node is spawned with the `--restricted` flag. security: - bearerAuth: [ ] tags: diff --git a/pkg/api/api.go b/pkg/api/api.go index fec8ab44afe..a7eea80cb30 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -11,7 +11,6 @@ import ( "crypto/ecdsa" "encoding/base64" "encoding/hex" - "encoding/json" "errors" "fmt" "io" @@ -28,7 +27,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethersphere/bee/v2/pkg/accounting" - "github.com/ethersphere/bee/v2/pkg/auth" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/feeds" "github.com/ethersphere/bee/v2/pkg/file/pipeline" @@ -136,7 +134,6 @@ type PinIntegrity interface { } type Service struct { - auth auth.Authenticator storer Storer resolver resolver.Interface pss pss.Interface @@ -227,7 +224,6 @@ func (s *Service) SetRedistributionAgent(redistributionAgent *storageincentives. type Options struct { CORSAllowedOrigins []string WsPingPeriod time.Duration - Restricted bool } type ExtraOptions struct { @@ -313,8 +309,7 @@ func New( } // Configure will create a and initialize a new API service. -func (s *Service) Configure(signer crypto.Signer, auth auth.Authenticator, tracer *tracing.Tracer, o Options, e ExtraOptions, chainID int64, erc20 erc20.Service) { - s.auth = auth +func (s *Service) Configure(signer crypto.Signer, tracer *tracing.Tracer, o Options, e ExtraOptions, chainID int64, erc20 erc20.Service) { s.signer = signer s.Options = o s.tracer = tracer @@ -429,119 +424,6 @@ func (s *Service) resolveNameOrAddress(str string) (swarm.Address, error) { return swarm.ZeroAddress, fmt.Errorf("%w: %w", errInvalidNameOrAddress, err) } -type securityTokenRsp struct { - Key string `json:"key"` -} - -type securityTokenReq struct { - Role string `json:"role"` - Expiry int `json:"expiry"` // duration in seconds -} - -func (s *Service) authHandler(w http.ResponseWriter, r *http.Request) { - _, pass, ok := r.BasicAuth() - - if !ok { - s.logger.Error(nil, "auth handler: missing basic auth") - w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) - jsonhttp.Unauthorized(w, "Unauthorized") - return - } - - if !s.auth.Authorize(pass) { - s.logger.Error(nil, "auth handler: unauthorized") - w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) - jsonhttp.Unauthorized(w, "Unauthorized") - return - } - - body, err := io.ReadAll(r.Body) - if err != nil { - s.logger.Debug("auth handler: read request body failed", "error", err) - s.logger.Error(nil, "auth handler: read request body failed") - jsonhttp.BadRequest(w, "Read request body") - return - } - - var payload securityTokenReq - if err = json.Unmarshal(body, &payload); err != nil { - s.logger.Debug("auth handler: unmarshal request body failed", "error", err) - s.logger.Error(nil, "auth handler: unmarshal request body failed") - jsonhttp.BadRequest(w, "Unmarshal json body") - return - } - - key, err := s.auth.GenerateKey(payload.Role, time.Duration(payload.Expiry)*time.Second) - if errors.Is(err, auth.ErrExpiry) { - s.logger.Debug("auth handler: generate key failed", "error", err) - s.logger.Error(nil, "auth handler: generate key failed") - jsonhttp.BadRequest(w, "Expiry duration must be a positive number") - return - } - if err != nil { - s.logger.Debug("auth handler: add auth token failed", "error", err) - s.logger.Error(nil, "auth handler: add auth token failed") - jsonhttp.InternalServerError(w, "Error generating authorization token") - return - } - - jsonhttp.Created(w, securityTokenRsp{ - Key: key, - }) -} - -func (s *Service) refreshHandler(w http.ResponseWriter, r *http.Request) { - reqToken := r.Header.Get(AuthorizationHeader) - if !strings.HasPrefix(reqToken, "Bearer ") { - jsonhttp.Forbidden(w, "Missing bearer token") - return - } - - keys := strings.Split(reqToken, "Bearer ") - - if len(keys) != 2 || strings.Trim(keys[1], " ") == "" { - jsonhttp.Forbidden(w, "Missing security token") - return - } - - authToken := keys[1] - - body, err := io.ReadAll(r.Body) - if err != nil { - s.logger.Debug("auth handler: read request body failed", "error", err) - s.logger.Error(nil, "auth handler: read request body failed") - jsonhttp.BadRequest(w, "Read request body") - return - } - - var payload securityTokenReq - if err = json.Unmarshal(body, &payload); err != nil { - s.logger.Debug("auth handler: unmarshal request body failed", "error", err) - s.logger.Error(nil, "auth handler: unmarshal request body failed") - jsonhttp.BadRequest(w, "Unmarshal json body") - return - } - - key, err := s.auth.RefreshKey(authToken, time.Duration(payload.Expiry)*time.Second) - if errors.Is(err, auth.ErrTokenExpired) { - s.logger.Debug("auth handler: refresh key failed", "error", err) - s.logger.Error(nil, "auth handler: refresh key failed") - jsonhttp.BadRequest(w, "Token expired") - return - } - - if err != nil { - s.logger.Debug("auth handler: refresh token failed", "error", err) - s.logger.Error(nil, "auth handler: refresh token failed") - jsonhttp.InternalServerError(w, "Error refreshing authorization token") - return - } - - jsonhttp.Created(w, securityTokenRsp{ - Key: key, - }) -} - func (s *Service) newTracingHandler(spanName string) func(h http.Handler) http.Handler { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index bf2c5288c5a..b8c8044998a 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -25,8 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common" accountingmock "github.com/ethersphere/bee/v2/pkg/accounting/mock" "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/auth" - mockauth "github.com/ethersphere/bee/v2/pkg/auth/mock" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/feeds" "github.com/ethersphere/bee/v2/pkg/file/pipeline" @@ -104,8 +102,6 @@ type testServerOptions struct { Post postage.Service Steward steward.Interface WsHeaders http.Header - Authenticator auth.Authenticator - Restricted bool DirectUpload bool Probe *api.Probe @@ -157,13 +153,7 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket. if o.SyncStatus == nil { o.SyncStatus = func() (bool, error) { return true, nil } } - if o.Authenticator == nil { - o.Authenticator = &mockauth.Auth{ - EnforceFunc: func(_, _, _ string) (bool, error) { - return true, nil - }, - } - } + var chanStore *chanStorer topologyDriver := topologymock.NewTopologyDriver(o.TopologyOpts...) @@ -229,10 +219,9 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket. }) testutil.CleanupCloser(t, tracerCloser) - s.Configure(signer, o.Authenticator, noOpTracer, api.Options{ + s.Configure(signer, noOpTracer, api.Options{ CORSAllowedOrigins: o.CORSAllowedOrigins, WsPingPeriod: o.WsPingPeriod, - Restricted: o.Restricted, }, extraOpts, 1, erc20) s.MountTechnicalDebug() @@ -380,7 +369,7 @@ func TestParseName(t *testing.T) { signer := crypto.NewDefaultSigner(pk) s := api.New(pk.PublicKey, pk.PublicKey, common.Address{}, nil, log, nil, nil, 1, false, false, nil, []string{"*"}, inmemstore.New()) - s.Configure(signer, nil, nil, api.Options{}, api.ExtraOptions{Resolver: tC.res}, 1, nil) + s.Configure(signer, nil, api.Options{}, api.ExtraOptions{Resolver: tC.res}, 1, nil) s.MountAPI() tC := tC diff --git a/pkg/api/auth_test.go b/pkg/api/auth_test.go deleted file mode 100644 index f2cb0a99d59..00000000000 --- a/pkg/api/auth_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2021 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package api_test - -import ( - "errors" - "net/http" - "testing" - - "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/auth/mock" - "github.com/ethersphere/bee/v2/pkg/jsonhttp" - "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" - "github.com/ethersphere/bee/v2/pkg/log" -) - -// nolint:paralleltest -func TestAuth(t *testing.T) { - var ( - resource = "/auth" - logger = log.Noop - authenticator = &mock.Auth{ - AuthorizeFunc: func(string) bool { return true }, - GenerateKeyFunc: func(string) (string, error) { return "123", nil }, - } - client, _, _, _ = newTestServer(t, testServerOptions{ - Logger: logger, - Restricted: true, - Authenticator: authenticator, - }) - ) - - t.Run("missing authorization header", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusUnauthorized, - jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Unauthorized", - Code: http.StatusUnauthorized, - }), - ) - }) - t.Run("missing role", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusBadRequest, - jsonhttptest.WithRequestHeader(api.AuthorizationHeader, "Basic dGVzdDp0ZXN0"), - jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Unmarshal json body", - Code: http.StatusBadRequest, - }), - ) - }) - t.Run("bad authorization header", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusUnauthorized, - jsonhttptest.WithRequestHeader(api.AuthorizationHeader, "Basic dGV"), - jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Unauthorized", - Code: http.StatusUnauthorized, - }), - ) - }) - t.Run("bad request body", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusBadRequest, - jsonhttptest.WithRequestHeader(api.AuthorizationHeader, "Basic dGVzdDp0ZXN0"), - - jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Unmarshal json body", - Code: http.StatusBadRequest, - }), - ) - }) - t.Run("unauthorized", func(t *testing.T) { - original := authenticator.AuthorizeFunc - authenticator.AuthorizeFunc = func(string) bool { return false } - defer func() { - authenticator.AuthorizeFunc = original - }() - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusUnauthorized, - jsonhttptest.WithRequestHeader(api.AuthorizationHeader, "Basic dGVzdDp0ZXN0"), - - jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Unauthorized", - Code: http.StatusUnauthorized, - }), - ) - }) - t.Run("failed to add key", func(t *testing.T) { - original := authenticator.GenerateKeyFunc - authenticator.GenerateKeyFunc = func(s string) (string, error) { - return "", errors.New("error adding key") - } - defer func() { - authenticator.GenerateKeyFunc = original - }() - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusInternalServerError, - jsonhttptest.WithRequestHeader(api.AuthorizationHeader, "Basic dGVzdDp0ZXN0"), - jsonhttptest.WithJSONRequestBody(api.SecurityTokenRequest{ - Role: "consumer", - }), - jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ - Message: "Error generating authorization token", - Code: http.StatusInternalServerError, - }), - ) - }) - t.Run("success", func(t *testing.T) { - jsonhttptest.Request(t, client, http.MethodPost, resource, http.StatusCreated, - jsonhttptest.WithRequestHeader(api.AuthorizationHeader, "Basic dGVzdDp0ZXN0"), - jsonhttptest.WithJSONRequestBody(api.SecurityTokenRequest{ - Role: "consumer", - }), - jsonhttptest.WithExpectedJSONResponse(api.SecurityTokenResponse{ - Key: "123", - }), - ) - }) -} diff --git a/pkg/api/export_test.go b/pkg/api/export_test.go index 812ce522ba0..6eba8a56841 100644 --- a/pkg/api/export_test.go +++ b/pkg/api/export_test.go @@ -18,8 +18,6 @@ type ( TagRequest = tagRequest ListTagsResponse = listTagsResponse IsRetrievableResponse = isRetrievableResponse - SecurityTokenResponse = securityTokenRsp - SecurityTokenRequest = securityTokenReq ) var ( diff --git a/pkg/api/router.go b/pkg/api/router.go index aaa75725b09..e07f406bec7 100644 --- a/pkg/api/router.go +++ b/pkg/api/router.go @@ -11,7 +11,6 @@ import ( "net/http/pprof" "strings" - "github.com/ethersphere/bee/v2/pkg/auth" "github.com/ethersphere/bee/v2/pkg/jsonhttp" "github.com/ethersphere/bee/v2/pkg/log/httpaccess" "github.com/ethersphere/bee/v2/pkg/swarm" @@ -142,11 +141,7 @@ func (s *Service) mountTechnicalDebug() { s.router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) s.router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace)) - pprofRootHandlerF := pprof.Index - if s.Restricted { - pprofRootHandlerF = web.ChainHandlers(auth.PermissionCheckHandler(s.auth), web.FinalHandler(http.HandlerFunc(pprof.Index))).ServeHTTP - } - s.router.PathPrefix("/debug/pprof/").Handler(http.HandlerFunc(pprofRootHandlerF)) + s.router.PathPrefix("/debug/pprof/").Handler(http.HandlerFunc(pprof.Index)) s.router.Handle("/debug/vars", expvar.Handler()) s.router.Handle("/loggers", jsonhttp.MethodHandler{ @@ -351,28 +346,10 @@ func (s *Service) mountAPI() { httpaccess.NewHTTPAccessSuppressLogHandler(), web.FinalHandlerFunc(s.healthHandler), )) - - if s.Restricted { - handle("/auth", jsonhttp.MethodHandler{ - "POST": web.ChainHandlers( - jsonhttp.NewMaxBodyBytesHandler(512), - web.FinalHandlerFunc(s.authHandler), - ), - }) - handle("/refresh", jsonhttp.MethodHandler{ - "POST": web.ChainHandlers( - jsonhttp.NewMaxBodyBytesHandler(512), - web.FinalHandlerFunc(s.refreshHandler), - ), - }) - } } func (s *Service) mountBusinessDebug() { handle := func(path string, handler http.Handler) { - if s.Restricted { - handler = web.ChainHandlers(auth.PermissionCheckHandler(s.auth), web.FinalHandler(handler)) - } s.router.Handle(path, handler) s.router.Handle(rootPath+path, handler) } diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go deleted file mode 100644 index a5aaec89dd2..00000000000 --- a/pkg/auth/auth.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2021 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package auth - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/md5" - "crypto/rand" - "encoding/base64" - "encoding/hex" - "encoding/json" - "errors" - "io" - "time" - - "github.com/casbin/casbin/v2" - "github.com/casbin/casbin/v2/model" - "github.com/ethersphere/bee/v2/pkg/log" - "golang.org/x/crypto/bcrypt" -) - -// loggerName is the tree path name of the logger for this package. -const loggerName = "auth" - -type Authenticator interface { - Authorize(string) bool - GenerateKey(string, time.Duration) (string, error) - RefreshKey(string, time.Duration) (string, error) - Enforce(string, string, string) (bool, error) -} - -type authRecord struct { - Role string `json:"r"` - Expiry time.Time `json:"e"` -} - -type authenticator struct { - passwordHash []byte - ciph *encrypter - enforcer *casbin.Enforcer - log log.Logger -} - -func New(encryptionKey, passwordHash string, logger log.Logger) (*authenticator, error) { - m, err := model.NewModelFromString(` - [request_definition] - r = sub, obj, act - - [role_definition] - g = _, _ - - [policy_definition] - p = sub, obj, act - - [policy_effect] - e = some(where (p.eft == allow)) - - [matchers] - m = (g(r.sub, p.sub) || r.sub == p.sub) && (keyMatch(r.obj, p.obj) || keyMatch(r.obj, '/v1'+p.obj)) && regexMatch(r.act, p.act)`) - - if err != nil { - return nil, err - } - - e, err := casbin.NewEnforcer(m) - if err != nil { - return nil, err - } - - if err := applyPolicies(e); err != nil { - return nil, err - } - - ciph, err := newEncrypter([]byte(encryptionKey)) - if err != nil { - return nil, err - } - - auth := authenticator{ - enforcer: e, - ciph: ciph, - passwordHash: []byte(passwordHash), - log: logger.WithName(loggerName).Register(), - } - - return &auth, nil -} - -func (a *authenticator) Authorize(password string) bool { - return nil == bcrypt.CompareHashAndPassword(a.passwordHash, []byte(password)) -} - -var ErrExpiry = errors.New("expiry duration must be a positive number") - -func (a *authenticator) GenerateKey(role string, expiryDuration time.Duration) (string, error) { - if expiryDuration == 0 { - return "", ErrExpiry - } - - ar := authRecord{ - Role: role, - Expiry: time.Now().Add(expiryDuration), - } - - data, err := json.Marshal(ar) - if err != nil { - return "", err - } - - encryptedBytes, err := a.ciph.encrypt(data) - if err != nil { - return "", err - } - - apiKey := base64.StdEncoding.EncodeToString(encryptedBytes) - - return apiKey, nil -} - -var ErrTokenExpired = errors.New("token expired") - -func (a *authenticator) RefreshKey(apiKey string, expiryDuration time.Duration) (string, error) { - if expiryDuration == 0 { - return "", ErrExpiry - } - - decoded, err := base64.StdEncoding.DecodeString(apiKey) - if err != nil { - return "", err - } - - decryptedBytes, err := a.ciph.decrypt(decoded) - if err != nil { - return "", err - } - - var ar authRecord - if err := json.Unmarshal(decryptedBytes, &ar); err != nil { - return "", err - } - - if time.Now().After(ar.Expiry) { - return "", ErrTokenExpired - } - - ar.Expiry = time.Now().Add(expiryDuration) - - data, err := json.Marshal(ar) - if err != nil { - return "", err - } - - encryptedBytes, err := a.ciph.encrypt(data) - if err != nil { - return "", err - } - - apiKey = base64.StdEncoding.EncodeToString(encryptedBytes) - - return apiKey, nil -} - -func (a *authenticator) Enforce(apiKey, obj, act string) (bool, error) { - decoded, err := base64.StdEncoding.DecodeString(apiKey) - if err != nil { - a.log.Error(err, "decode token failed") - return false, err - } - - decryptedBytes, err := a.ciph.decrypt(decoded) - if err != nil { - a.log.Error(err, "decrypt token failed") - return false, err - } - - var ar authRecord - if err := json.Unmarshal(decryptedBytes, &ar); err != nil { - a.log.Error(err, "unmarshal token failed") - return false, err - } - - if time.Now().After(ar.Expiry) { - a.log.Error(nil, "token expired") - return false, ErrTokenExpired - } - - allow, err := a.enforcer.Enforce(ar.Role, obj, act) - if err != nil { - a.log.Error(err, "enforce failed") - return false, err - } - - return allow, nil -} - -type encrypter struct { - gcm cipher.AEAD -} - -func newEncrypter(key []byte) (*encrypter, error) { - hasher := md5.New() - _, err := hasher.Write(key) - if err != nil { - return nil, err - } - hash := hex.EncodeToString(hasher.Sum(nil)) - block, err := aes.NewCipher([]byte(hash)) - if err != nil { - return nil, err - } - gcm, err := cipher.NewGCM(block) - if err != nil { - return nil, err - } - - return &encrypter{ - gcm: gcm, - }, nil -} - -func (e encrypter) encrypt(data []byte) ([]byte, error) { - nonce := make([]byte, e.gcm.NonceSize()) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { - return nil, err - } - ciphertext := e.gcm.Seal(nonce, nonce, data, nil) - return ciphertext, nil -} - -func (e encrypter) decrypt(data []byte) ([]byte, error) { - nonceSize := e.gcm.NonceSize() - nonce, ciphertext := data[:nonceSize], data[nonceSize:] - plaintext, err := e.gcm.Open(nil, nonce, ciphertext, nil) - if err != nil { - return nil, err - } - return plaintext, nil -} - -func applyPolicies(e *casbin.Enforcer) error { - _, err := e.AddPolicies([][]string{ - {"consumer", "/bytes/*", "(GET)|(HEAD)"}, - {"creator", "/bytes", "POST"}, - {"consumer", "/chunks/*", "GET"}, - {"creator", "/chunks", "POST"}, - {"consumer", "/bzz/*", "GET"}, - {"creator", "/bzz/*", "PATCH"}, - {"creator", "/bzz", "POST"}, - {"creator", "/bzz?*", "POST"}, - {"consumer", "/bzz/*/*", "(GET)|(HEAD)"}, - {"creator", "/tags", "GET"}, - {"creator", "/tags?*", "GET"}, - {"creator", "/tags", "POST"}, - {"creator", "/tags/*", "(GET)|(DELETE)|(PATCH)"}, - {"creator", "/pins/*", "(GET)|(DELETE)|(POST)"}, - {"maintainer", "/pins", "GET"}, - {"creator", "/pss/send/*", "POST"}, - {"consumer", "/pss/subscribe/*", "GET"}, - {"creator", "/soc/*/*", "POST"}, - {"creator", "/feeds/*/*", "POST"}, - {"consumer", "/feeds/*/*", "GET"}, - {"maintainer", "/stamps", "GET"}, - {"maintainer", "/stamps/*", "GET"}, - {"maintainer", "/stamps/*/*", "POST"}, - {"maintainer", "/stamps/topup/*/*", "PATCH"}, - {"maintainer", "/stamps/dilute/*/*", "PATCH"}, - {"maintainer", "/stake", "(GET)|(DELETE)"}, - {"maintainer", "/stake/*", "POST"}, - {"maintainer", "/addresses", "GET"}, - {"maintainer", "/blocklist", "GET"}, - {"maintainer", "/connect/*", "POST"}, - {"maintainer", "/peers", "GET"}, - {"maintainer", "/peers/*", "DELETE"}, - {"maintainer", "/pingpong/*", "POST"}, - {"maintainer", "/topology", "GET"}, - {"maintainer", "/welcome-message", "(GET)|(POST)"}, - {"maintainer", "/balances", "GET"}, - {"maintainer", "/balances/*", "GET"}, - {"maintainer", "/accounting", "GET"}, - {"maintainer", "/chequebook/cashout/*", "GET"}, - {"accountant", "/chequebook/cashout/*", "POST"}, - {"accountant", "/chequebook/withdraw", "POST"}, - {"accountant", "/chequebook/withdraw?*", "POST"}, - {"accountant", "/chequebook/deposit", "POST"}, - {"accountant", "/chequebook/deposit?*", "POST"}, - {"maintainer", "/chequebook/cheque/*", "GET"}, - {"maintainer", "/chequebook/cheque", "GET"}, - {"maintainer", "/chequebook/address", "GET"}, - {"maintainer", "/chequebook/balance", "GET"}, - {"maintainer", "/wallet", "GET"}, - {"maintainer", "/wallet/withdraw/*", "POST"}, - {"maintainer", "/chunks/*", "(GET)|(DELETE)"}, - {"maintainer", "/reservestate", "GET"}, - {"maintainer", "/chainstate", "GET"}, - {"maintainer", "/settlements/*", "GET"}, - {"maintainer", "/settlements", "GET"}, - {"maintainer", "/transactions", "GET"}, - {"consumer", "/transactions/*", "GET"}, - {"accountant", "/transactions/*", "(POST)|(DELETE)"}, - {"consumer", "/consumed", "GET"}, - {"consumer", "/consumed/*", "GET"}, - {"consumer", "/chunks/stream", "GET"}, - {"creator", "/stewardship/*", "GET"}, - {"consumer", "/stewardship/*", "PUT"}, - {"maintainer", "/redistributionstate", "GET"}, - {"maintainer", "/debugstore", "GET"}, - {"consumer", "/rchash", "GET"}, - {"maintainer", "/debug/*", "GET"}, - {"maintainer", "/metrics", "GET"}, - {"maintainer", "/node", "GET"}, - {"maintainer", "/loggers", "GET"}, - {"maintainer", "/loggers/*", "(GET)|(PUT)"}, - {"maintainer", "/status", "GET"}, - {"maintainer", "/status/peers", "GET"}, - {"maintainer", "/rcash/*", "GET"}, - {"maintainer", "/batches", "GET"}, - {"maintainer", "/timesettlements", "GET"}, - }) - - if err != nil { - return err - } - - // consumer > creator > accountant > maintainer - _, err = e.AddGroupingPolicies([][]string{ - {"creator", "consumer"}, - {"accountant", "creator"}, - {"maintainer", "accountant"}, - }) - - return err -} diff --git a/pkg/auth/auth_test.go b/pkg/auth/auth_test.go deleted file mode 100644 index 0d107a764a2..00000000000 --- a/pkg/auth/auth_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2021 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package auth_test - -import ( - "errors" - "testing" - "time" - - "github.com/ethersphere/bee/v2/pkg/auth" - "github.com/ethersphere/bee/v2/pkg/log" -) - -const ( - encryptionKey = "mZIODMvjsiS2VdK1xgI1cOTizhGVNoVz" - passwordHash = "$2a$12$mZIODMvjsiS2VdK1xgI1cOTizhGVNoVz2Xn48H8ddFFLzX2B3lD3m" -) - -func TestAuthorize(t *testing.T) { - t.Parallel() - - a, err := auth.New(encryptionKey, passwordHash, log.Noop) - if err != nil { - t.Error(err) - } - - tt := []struct { - desc string - pass string - expected bool - }{ - { - desc: "correct credentials", - pass: "test", - expected: true, - }, { - desc: "wrong password", - pass: "notTest", - expected: false, - }, - } - for _, tC := range tt { - tC := tC - t.Run(tC.desc, func(t *testing.T) { - t.Parallel() - - res := a.Authorize(tC.pass) - if res != tC.expected { - t.Error("unexpected result", res) - } - }) - } -} - -func TestExpiry(t *testing.T) { - t.Parallel() - - const expiryDuration = time.Millisecond * 10 - - a, err := auth.New(encryptionKey, passwordHash, log.Noop) - if err != nil { - t.Error(err) - } - - key, err := a.GenerateKey("consumer", expiryDuration) - if err != nil { - t.Errorf("expected no error, got: %v", err) - } - - time.Sleep(expiryDuration * 2) - - result, err := a.Enforce(key, "/bytes/1", "GET") - if !errors.Is(err, auth.ErrTokenExpired) { - t.Errorf("expected token expired error, got: %v", err) - } - - if result { - t.Errorf("expected %v, got %v", false, result) - } -} - -func TestEnforce(t *testing.T) { - t.Parallel() - - const expiryDuration = time.Second - - a, err := auth.New(encryptionKey, passwordHash, log.Noop) - if err != nil { - t.Error(err) - } - - tt := []struct { - desc string - role, resource, action string - expected bool - }{ - { - desc: "success", - role: "maintainer", - resource: "/pingpong/someone", - action: "POST", - expected: true, - }, { - desc: "success with query param", - role: "creator", - resource: "/bzz?name=some-name", - action: "POST", - expected: true, - }, - { - desc: "bad role", - role: "consumer", - resource: "/pingpong/some-other-peer", - action: "POST", - }, - { - desc: "bad resource", - role: "maintainer", - resource: "/i-dont-exist", - action: "POST", - }, - { - desc: "bad action", - role: "maintainer", - resource: "/pingpong/someone", - action: "DELETE", - }, - } - - for _, tC := range tt { - tC := tC - t.Run(tC.desc, func(t *testing.T) { - t.Parallel() - - apiKey, err := a.GenerateKey(tC.role, expiryDuration) - - if err != nil { - t.Errorf("expected no error, got: %v", err) - } - - result, err := a.Enforce(apiKey, tC.resource, tC.action) - - if err != nil { - t.Errorf("expected no error, got: %v", err) - } - - if result != tC.expected { - t.Errorf("request from user with %s on object %s: expected %v, got %v", tC.role, tC.resource, tC.expected, result) - } - }) - } -} diff --git a/pkg/auth/handler.go b/pkg/auth/handler.go deleted file mode 100644 index 6a54b9269be..00000000000 --- a/pkg/auth/handler.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2021 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package auth - -import ( - "errors" - "net/http" - "strings" - - "github.com/ethersphere/bee/v2/pkg/jsonhttp" -) - -type auth interface { - Enforce(string, string, string) (bool, error) -} - -func PermissionCheckHandler(auth auth) func(h http.Handler) http.Handler { - return func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - reqToken := r.Header.Get("Authorization") - if !strings.HasPrefix(reqToken, "Bearer ") { - jsonhttp.Forbidden(w, "Missing bearer token") - return - } - - keys := strings.Split(reqToken, "Bearer ") - - if len(keys) != 2 || strings.Trim(keys[1], " ") == "" { - jsonhttp.Unauthorized(w, "Missing security token") - return - } - - apiKey := keys[1] - - allowed, err := auth.Enforce(apiKey, r.URL.Path, r.Method) - if errors.Is(err, ErrTokenExpired) { - jsonhttp.Unauthorized(w, "Token expired") - return - } - - if err != nil { - jsonhttp.InternalServerError(w, "Error occurred while validating the security token") - return - } - - if !allowed { - jsonhttp.Forbidden(w, "Provided security token does not grant access to the resource") - return - } - - h.ServeHTTP(w, r) - }) - } -} diff --git a/pkg/auth/main_test.go b/pkg/auth/main_test.go deleted file mode 100644 index be220f06760..00000000000 --- a/pkg/auth/main_test.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2022 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package auth_test - -import ( - "testing" - - "go.uber.org/goleak" -) - -func TestMain(m *testing.M) { - goleak.VerifyTestMain(m) -} diff --git a/pkg/auth/mock/auth.go b/pkg/auth/mock/auth.go deleted file mode 100644 index ef8ebd30b75..00000000000 --- a/pkg/auth/mock/auth.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2021 The Swarm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mock - -import "time" - -type Auth struct { - AuthorizeFunc func(string) bool - GenerateKeyFunc func(string) (string, error) - EnforceFunc func(string, string, string) (bool, error) -} - -func (ma *Auth) Authorize(u string) bool { - if ma.AuthorizeFunc == nil { - return true - } - return ma.AuthorizeFunc(u) -} -func (ma *Auth) GenerateKey(k string, _ time.Duration) (string, error) { - if ma.GenerateKeyFunc == nil { - return "", nil - } - return ma.GenerateKeyFunc(k) -} -func (ma *Auth) RefreshKey(k string, _ time.Duration) (string, error) { - if ma.GenerateKeyFunc == nil { - return "", nil - } - return ma.GenerateKeyFunc(k) -} -func (ma *Auth) Enforce(a1 string, a2 string, a3 string) (bool, error) { - return ma.EnforceFunc(a1, a2, a3) -} diff --git a/pkg/node/devnode.go b/pkg/node/devnode.go index 2c64f990591..fe9476d9d00 100644 --- a/pkg/node/devnode.go +++ b/pkg/node/devnode.go @@ -19,7 +19,6 @@ import ( "github.com/ethereum/go-ethereum/common" mockAccounting "github.com/ethersphere/bee/v2/pkg/accounting/mock" "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/auth" "github.com/ethersphere/bee/v2/pkg/bzz" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/feeds/factory" @@ -79,9 +78,6 @@ type DevOptions struct { DBWriteBufferSize uint64 DBBlockCacheCapacity uint64 DBDisableSeeksCompaction bool - Restricted bool - TokenEncryptionKey string - AdminPasswordHash string } // NewDevBee starts the bee instance in 'development' mode @@ -139,15 +135,6 @@ func NewDevBee(logger log.Logger, o *DevOptions) (b *DevBee, err error) { return nil, fmt.Errorf("blockchain address: %w", err) } - var authenticator auth.Authenticator - - if o.Restricted { - if authenticator, err = auth.New(o.TokenEncryptionKey, o.AdminPasswordHash, logger); err != nil { - return nil, fmt.Errorf("authenticator: %w", err) - } - logger.Info("starting with restricted APIs") - } - var mockTransaction = transactionmock.New(transactionmock.WithPendingTransactionsFunc(func() ([]common.Hash, error) { return []common.Hash{common.HexToHash("abcd")}, nil }), transactionmock.WithResendTransactionFunc(func(ctx context.Context, txHash common.Hash) error { @@ -367,10 +354,9 @@ func NewDevBee(logger log.Logger, o *DevOptions) (b *DevBee, err error) { apiService := api.New(mockKey.PublicKey, mockKey.PublicKey, overlayEthAddress, nil, logger, mockTransaction, batchStore, api.DevMode, true, true, chainBackend, o.CORSAllowedOrigins, inmemstore.New()) - apiService.Configure(signer, authenticator, tracer, api.Options{ + apiService.Configure(signer, tracer, api.Options{ CORSAllowedOrigins: o.CORSAllowedOrigins, WsPingPeriod: 60 * time.Second, - Restricted: o.Restricted, }, debugOpts, 1, erc20) apiService.MountTechnicalDebug() apiService.MountDebug() diff --git a/pkg/node/node.go b/pkg/node/node.go index f50574cdecc..5f799298164 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -27,7 +27,6 @@ import ( "github.com/ethersphere/bee/v2/pkg/accounting" "github.com/ethersphere/bee/v2/pkg/addressbook" "github.com/ethersphere/bee/v2/pkg/api" - "github.com/ethersphere/bee/v2/pkg/auth" "github.com/ethersphere/bee/v2/pkg/config" "github.com/ethersphere/bee/v2/pkg/crypto" "github.com/ethersphere/bee/v2/pkg/feeds/factory" @@ -162,9 +161,6 @@ type Options struct { MutexProfile bool StaticNodes []swarm.Address AllowPrivateCIDRs bool - Restricted bool - TokenEncryptionKey string - AdminPasswordHash string UsePostageSnapshot bool EnableStorageIncentives bool StatestoreCacheCapacity uint64 @@ -368,15 +364,6 @@ func NewBee( b.transactionCloser = tracerCloser b.transactionMonitorCloser = transactionMonitor - var authenticator auth.Authenticator - - if o.Restricted { - if authenticator, err = auth.New(o.TokenEncryptionKey, o.AdminPasswordHash, logger); err != nil { - return nil, fmt.Errorf("authenticator: %w", err) - } - logger.Info("starting with restricted APIs") - } - beeNodeMode := api.LightMode if o.FullNodeMode { beeNodeMode = api.FullMode @@ -431,7 +418,6 @@ func NewBee( o.CORSAllowedOrigins, stamperStore, ) - apiService.Restricted = o.Restricted apiService.MountTechnicalDebug() apiService.SetProbe(probe) @@ -1089,10 +1075,9 @@ func NewBee( apiService.MustRegisterMetrics(swapService.Metrics()...) } - apiService.Configure(signer, authenticator, tracer, api.Options{ + apiService.Configure(signer, tracer, api.Options{ CORSAllowedOrigins: o.CORSAllowedOrigins, WsPingPeriod: 60 * time.Second, - Restricted: o.Restricted, }, extraOpts, chainID, erc20Service) apiService.MountDebug()