Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions pocs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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`).

> [!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

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)

### JWT

_Coming Soon_!
69 changes: 69 additions & 0 deletions pocs/obfuscated-endpoint-url/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 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.

## Deploying

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.

## Analytics

Using the analytics dashboard the account owner can see activity with this specific endpoint,
so by handing out individual endpoints the account owner can track how extensively the endpoint has been evaluated.

## Single-use & deleting

Thus one can extend thise concept to a "single-use" endpoint, for example creating an endpoint
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A minor typo

Suggested change
Thus one can extend thise concept to a "single-use" endpoint, for example creating an endpoint
Thus one can extend this 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
```

## 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.

```
> stepzen list --folder pocs
Endpoint Created at Updated at
──────────────────────────────────────────────────────────────────────── ──────────────────────── ─────────────────────
pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe Sep 8, 2024, 12:46 PM Sep 8, 2024, 12:59 PM
```

## 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.

```
> stepzen request '{__schema{description}}'
{
"data": {
"__schema": {
"description": "Sample mocked Customer endpoint."
}
}
}
```
5 changes: 5 additions & 0 deletions pocs/obfuscated-endpoint-url/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
access:
policies:
- type: Query
policyDefault:
condition: true # allow all fields in Query with no authorization
22 changes: 22 additions & 0 deletions pocs/obfuscated-endpoint-url/index.graphql
Original file line number Diff line number Diff line change
@@ -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
}
11 changes: 11 additions & 0 deletions pocs/obfuscated-endpoint-url/operations.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
query Customer($id: ID!) {
customer(id: $id) {
id
name
email
address {
city
zip
}
}
}
3 changes: 3 additions & 0 deletions pocs/obfuscated-endpoint-url/stepzen.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"endpoint": "api/misc"
}
37 changes: 37 additions & 0 deletions pocs/obfuscated-endpoint-url/tests/Test.js
Original file line number Diff line number Diff line change
@@ -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: "[email protected]",
address: {
city: "New Schroeder",
zip: "36897",
},
},
},
},
];
return deployAndRun(__dirname, tests);
});