From fc2bc57678e933af7117729179d434aea06c0d74 Mon Sep 17 00:00:00 2001 From: Dan Debrunner Date: Sun, 8 Sep 2024 13:19:03 -0400 Subject: [PATCH 1/4] chore: obfuscated endpoint url snippet --- pocs/README.md | 30 ++++++++++ pocs/obfuscated-endpoint-url/README.md | 59 +++++++++++++++++++ pocs/obfuscated-endpoint-url/config.yaml | 5 ++ pocs/obfuscated-endpoint-url/index.graphql | 22 +++++++ .../stepzen.config.json | 3 + 5 files changed, 119 insertions(+) create mode 100644 pocs/README.md create mode 100644 pocs/obfuscated-endpoint-url/README.md create mode 100644 pocs/obfuscated-endpoint-url/config.yaml create mode 100644 pocs/obfuscated-endpoint-url/index.graphql create mode 100644 pocs/obfuscated-endpoint-url/stepzen.config.json diff --git a/pocs/README.md b/pocs/README.md new file mode 100644 index 0000000..8e69536 --- /dev/null +++ b/pocs/README.md @@ -0,0 +1,30 @@ +# Developing PoCs. + +## Sharing + +When developing a GraphQL PoC using IBM API Connect Essentials (StepZen) you will typically +want to share the endpoint to allow others to evaluate it by making GraphQL requests against it. + +### Admin key + +> [!CAUTION] +> Never share an endpoint by handing out the account's adminkey (`stepzen whoami --adminkey`). + +### API key + +The most simple (but somewhat risky) approach is to share the account's apikey (`stepzen whoami --apikey`). + +The disadvantage with this is the admin key grants access to all endpoints within an account. +Thus if you are working on different PoCs, by providing access to one you provide access to all +which could leak information between different departments or clients. + +### Obfuscated endpoints + +Obfuscated endpoints allow sharing without handing out any keys or tokens. + +The concept can include single-use or short-lived endpoints for a demos, or time-limited evaluations. + +> [!WARNING] +> Obfuscated endpoints are public, but have a hard to guess endpoint URL so anyone with the URL has access to the API. + +See [obfuscated-endpoint-url](obfuscated-endpoint-url/README.md) diff --git a/pocs/obfuscated-endpoint-url/README.md b/pocs/obfuscated-endpoint-url/README.md new file mode 100644 index 0000000..68dc48f --- /dev/null +++ b/pocs/obfuscated-endpoint-url/README.md @@ -0,0 +1,59 @@ +# Obfuscated endpoint URL + +One simple mechanism to share an IBM API Connect Essentials (StepZen) endpoint to +to make the [endpoint open](../../protection/makeAllPublic/config.yaml) but +deploy the schema with an obfuscated name. + +For example, deploy this schema using a randomly generated name (Linux/MacOS): + +``` +name=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z' | fold -w 64 | head -n 1) +stepzen deploy pocs/$name +``` + +You will see the endpoint is deployed with a random obfuscated URL. + +``` +Deploying pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe to StepZen... done in 511ms 🚀 + ✓ 🔐 https://danville.us-east-a.ibm.stepzen.net/pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe/__graphql + ✓ 🔐 wss://danville.us-east-a.ibm.stepzen.net/stepzen-subscriptions/pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe/__graphql (subscriptions) +``` + +This endpoint URL can now be handed out to allow others to evaluate the endpoint without requiring any authorization. + +> [!WARNING] +> Anyone with the URL has access to the endpoint, so this is security through obscurity. + +Using analytics the account owner can see activity with this specific endpoint, +so be handing out individual endpoints the account owner can track who has evaluated the endpoint. + +Thus one can extend thise concept to a "single-use" endpoint, for example creating an endpoint +for a demo and then delete it when no longer required. + +``` +stepzen delete --non-interactive pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe +``` + +By maintaining such endpoints in single folder, such as `pocs` or `single-use` you can use `stepzen list` to +see which endpoints are still active. + +``` +> stepzen list --folder pocs + Endpoint Created at Updated at + ──────────────────────────────────────────────────────────────────────── ──────────────────────── ───────────────────── + pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe Sep 8, 2024, 12:46 PM Sep 8, 2024, 12:59 PM +``` + +It is recommended to define a schema description so that this GraphQL introspection request can +used to see the purpose of the obfuscated endpoint. + +``` +> stepzen request '{__schema{description}}' +{ + "data": { + "__schema": { + "description": "Sample mocked Customer endpoint." + } + } +} +``` diff --git a/pocs/obfuscated-endpoint-url/config.yaml b/pocs/obfuscated-endpoint-url/config.yaml new file mode 100644 index 0000000..86c88bf --- /dev/null +++ b/pocs/obfuscated-endpoint-url/config.yaml @@ -0,0 +1,5 @@ +access: + policies: + - type: Query + policyDefault: + condition: true # allow all fields in Query with no authorization diff --git a/pocs/obfuscated-endpoint-url/index.graphql b/pocs/obfuscated-endpoint-url/index.graphql new file mode 100644 index 0000000..13d6b71 --- /dev/null +++ b/pocs/obfuscated-endpoint-url/index.graphql @@ -0,0 +1,22 @@ +""" +Sample mocked Customer endpoint. +""" +schema { + query: Query +} + +type Customer @mock { + id: ID! + name: String @mockfn(name: "LastName") + email: String @mockfn(name: "Email") + address: Address +} + +type Address { + city: String @mockfn(name: "City") + zip: String @mockfn(name: "Zip") +} + +type Query { + customer(id: ID): Customer +} diff --git a/pocs/obfuscated-endpoint-url/stepzen.config.json b/pocs/obfuscated-endpoint-url/stepzen.config.json new file mode 100644 index 0000000..63283a6 --- /dev/null +++ b/pocs/obfuscated-endpoint-url/stepzen.config.json @@ -0,0 +1,3 @@ +{ + "endpoint": "api/misc" +} \ No newline at end of file From 8550e06ae158596efa6bd5143b96454cd3f184e2 Mon Sep 17 00:00:00 2001 From: Dan Debrunner Date: Sun, 8 Sep 2024 13:27:30 -0400 Subject: [PATCH 2/4] chore: cleanup --- pocs/README.md | 6 +++--- pocs/obfuscated-endpoint-url/README.md | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/pocs/README.md b/pocs/README.md index 8e69536..544c6dc 100644 --- a/pocs/README.md +++ b/pocs/README.md @@ -14,9 +14,9 @@ want to share the endpoint to allow others to evaluate it by making GraphQL requ The most simple (but somewhat risky) approach is to share the account's apikey (`stepzen whoami --apikey`). -The disadvantage with this is the admin key grants access to all endpoints within an account. -Thus if you are working on different PoCs, by providing access to one you provide access to all -which could leak information between different departments or clients. +> [!WARNING] +> The admin key grants access to all endpoints within an account. Thus if you are working on different PoCs, by providing access to one you provide access to all +> which could leak information between different departments or clients. ### Obfuscated endpoints diff --git a/pocs/obfuscated-endpoint-url/README.md b/pocs/obfuscated-endpoint-url/README.md index 68dc48f..aa8bb85 100644 --- a/pocs/obfuscated-endpoint-url/README.md +++ b/pocs/obfuscated-endpoint-url/README.md @@ -4,6 +4,8 @@ One simple mechanism to share an IBM API Connect Essentials (StepZen) endpoint t to make the [endpoint open](../../protection/makeAllPublic/config.yaml) but deploy the schema with an obfuscated name. +## Deploying + For example, deploy this schema using a randomly generated name (Linux/MacOS): ``` @@ -24,9 +26,13 @@ This endpoint URL can now be handed out to allow others to evaluate the endpoint > [!WARNING] > Anyone with the URL has access to the endpoint, so this is security through obscurity. -Using analytics the account owner can see activity with this specific endpoint, +## Analytics + +Using the analytics dashboard the account owner can see activity with this specific endpoint, so be handing out individual endpoints the account owner can track who has evaluated the endpoint. +## Single-use & deleting + Thus one can extend thise concept to a "single-use" endpoint, for example creating an endpoint for a demo and then delete it when no longer required. @@ -34,6 +40,8 @@ for a demo and then delete it when no longer required. stepzen delete --non-interactive pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe ``` +## Tracking + By maintaining such endpoints in single folder, such as `pocs` or `single-use` you can use `stepzen list` to see which endpoints are still active. @@ -44,7 +52,9 @@ see which endpoints are still active. pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe Sep 8, 2024, 12:46 PM Sep 8, 2024, 12:59 PM ``` -It is recommended to define a schema description so that this GraphQL introspection request can +## Description + +It is recommended to define a [schema description](./index.graphql#L1-L6) so that this GraphQL introspection request can used to see the purpose of the obfuscated endpoint. ``` From 999709465a9839fcd70b13663621c5c71f7aa314 Mon Sep 17 00:00:00 2001 From: Dan Debrunner Date: Sun, 8 Sep 2024 13:31:10 -0400 Subject: [PATCH 3/4] chore: cleanup --- pocs/README.md | 4 ++++ pocs/obfuscated-endpoint-url/README.md | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pocs/README.md b/pocs/README.md index 544c6dc..7f7f617 100644 --- a/pocs/README.md +++ b/pocs/README.md @@ -28,3 +28,7 @@ The concept can include single-use or short-lived endpoints for a demos, or time > Obfuscated endpoints are public, but have a hard to guess endpoint URL so anyone with the URL has access to the API. See [obfuscated-endpoint-url](obfuscated-endpoint-url/README.md) + +### JWT + +_Coming Soon_! diff --git a/pocs/obfuscated-endpoint-url/README.md b/pocs/obfuscated-endpoint-url/README.md index aa8bb85..66e1ee0 100644 --- a/pocs/obfuscated-endpoint-url/README.md +++ b/pocs/obfuscated-endpoint-url/README.md @@ -29,7 +29,7 @@ This endpoint URL can now be handed out to allow others to evaluate the endpoint ## Analytics Using the analytics dashboard the account owner can see activity with this specific endpoint, -so be handing out individual endpoints the account owner can track who has evaluated the endpoint. +so by handing out individual endpoints the account owner can track how extensively the endpoint has been evaluated. ## Single-use & deleting @@ -52,7 +52,7 @@ see which endpoints are still active. pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe Sep 8, 2024, 12:46 PM Sep 8, 2024, 12:59 PM ``` -## Description +## Schema description It is recommended to define a [schema description](./index.graphql#L1-L6) so that this GraphQL introspection request can used to see the purpose of the obfuscated endpoint. From 830bd302773685acf942b972f41ddb9a6f1eb7b6 Mon Sep 17 00:00:00 2001 From: Dan Debrunner Date: Mon, 9 Sep 2024 09:16:17 -0400 Subject: [PATCH 4/4] test: add test for obfuscated-endpoint-url --- .../operations.graphql | 11 ++++++ pocs/obfuscated-endpoint-url/tests/Test.js | 37 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 pocs/obfuscated-endpoint-url/operations.graphql create mode 100644 pocs/obfuscated-endpoint-url/tests/Test.js diff --git a/pocs/obfuscated-endpoint-url/operations.graphql b/pocs/obfuscated-endpoint-url/operations.graphql new file mode 100644 index 0000000..d5d136e --- /dev/null +++ b/pocs/obfuscated-endpoint-url/operations.graphql @@ -0,0 +1,11 @@ +query Customer($id: ID!) { + customer(id: $id) { + id + name + email + address { + city + zip + } + } +} diff --git a/pocs/obfuscated-endpoint-url/tests/Test.js b/pocs/obfuscated-endpoint-url/tests/Test.js new file mode 100644 index 0000000..af88a99 --- /dev/null +++ b/pocs/obfuscated-endpoint-url/tests/Test.js @@ -0,0 +1,37 @@ +const fs = require("fs"); +const path = require("node:path"); + +const { + deployAndRun, + getTestDescription, +} = require("../../../tests/gqltest.js"); + +testDescription = getTestDescription("snippets", __dirname); + +const requestsFile = path.join(path.dirname(__dirname), "operations.graphql"); +const requests = fs.readFileSync(requestsFile, "utf8").toString(); + +describe(testDescription, function () { + const tests = [ + { + label: "customer", + query: requests, + operationName: "Customer", + variables: { + id: 1238, + }, + expected: { + customer: { + id: "1238", + name: "Baumbach", + email: "maxinebashirian@hilpert.com", + address: { + city: "New Schroeder", + zip: "36897", + }, + }, + }, + }, + ]; + return deployAndRun(__dirname, tests); +});