Skip to content

Commit bd54e6b

Browse files
authored
chore: obfuscated endpoint url snippet (#60)
* chore: obfuscated endpoint url snippet * chore: cleanup * chore: cleanup * test: add test for obfuscated-endpoint-url
1 parent edbb09f commit bd54e6b

File tree

7 files changed

+181
-0
lines changed

7 files changed

+181
-0
lines changed

pocs/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Developing PoCs.
2+
3+
## Sharing
4+
5+
When developing a GraphQL PoC using IBM API Connect Essentials (StepZen) you will typically
6+
want to share the endpoint to allow others to evaluate it by making GraphQL requests against it.
7+
8+
### Admin key
9+
10+
> [!CAUTION]
11+
> Never share an endpoint by handing out the account's adminkey (`stepzen whoami --adminkey`).
12+
13+
### API key
14+
15+
The most simple (but somewhat risky) approach is to share the account's apikey (`stepzen whoami --apikey`).
16+
17+
> [!WARNING]
18+
> 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
19+
> which could leak information between different departments or clients.
20+
21+
### Obfuscated endpoints
22+
23+
Obfuscated endpoints allow sharing without handing out any keys or tokens.
24+
25+
The concept can include single-use or short-lived endpoints for a demos, or time-limited evaluations.
26+
27+
> [!WARNING]
28+
> Obfuscated endpoints are public, but have a hard to guess endpoint URL so anyone with the URL has access to the API.
29+
30+
See [obfuscated-endpoint-url](obfuscated-endpoint-url/README.md)
31+
32+
### JWT
33+
34+
_Coming Soon_!
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Obfuscated endpoint URL
2+
3+
One simple mechanism to share an IBM API Connect Essentials (StepZen) endpoint to
4+
to make the [endpoint open](../../protection/makeAllPublic/config.yaml) but
5+
deploy the schema with an obfuscated name.
6+
7+
## Deploying
8+
9+
For example, deploy this schema using a randomly generated name (Linux/MacOS):
10+
11+
```
12+
name=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z' | fold -w 64 | head -n 1)
13+
stepzen deploy pocs/$name
14+
```
15+
16+
You will see the endpoint is deployed with a random obfuscated URL.
17+
18+
```
19+
Deploying pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe to StepZen... done in 511ms 🚀
20+
✓ 🔐 https://danville.us-east-a.ibm.stepzen.net/pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe/__graphql
21+
✓ 🔐 wss://danville.us-east-a.ibm.stepzen.net/stepzen-subscriptions/pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe/__graphql (subscriptions)
22+
```
23+
24+
This endpoint URL can now be handed out to allow others to evaluate the endpoint without requiring any authorization.
25+
26+
> [!WARNING]
27+
> Anyone with the URL has access to the endpoint, so this is security through obscurity.
28+
29+
## Analytics
30+
31+
Using the analytics dashboard the account owner can see activity with this specific endpoint,
32+
so by handing out individual endpoints the account owner can track how extensively the endpoint has been evaluated.
33+
34+
## Single-use & deleting
35+
36+
Thus one can extend thise concept to a "single-use" endpoint, for example creating an endpoint
37+
for a demo and then delete it when no longer required.
38+
39+
```
40+
stepzen delete --non-interactive pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe
41+
```
42+
43+
## Tracking
44+
45+
By maintaining such endpoints in single folder, such as `pocs` or `single-use` you can use `stepzen list` to
46+
see which endpoints are still active.
47+
48+
```
49+
> stepzen list --folder pocs
50+
Endpoint Created at Updated at
51+
──────────────────────────────────────────────────────────────────────── ──────────────────────── ─────────────────────
52+
pocs/FzOYquoOMuQzvQqsLSUfVuvQwfVwuOEhGOkGGpLDnuIzeJZCHQAfHbFMCCIQdmBe Sep 8, 2024, 12:46 PM Sep 8, 2024, 12:59 PM
53+
```
54+
55+
## Schema description
56+
57+
It is recommended to define a [schema description](./index.graphql#L1-L6) so that this GraphQL introspection request can
58+
used to see the purpose of the obfuscated endpoint.
59+
60+
```
61+
> stepzen request '{__schema{description}}'
62+
{
63+
"data": {
64+
"__schema": {
65+
"description": "Sample mocked Customer endpoint."
66+
}
67+
}
68+
}
69+
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
access:
2+
policies:
3+
- type: Query
4+
policyDefault:
5+
condition: true # allow all fields in Query with no authorization
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""
2+
Sample mocked Customer endpoint.
3+
"""
4+
schema {
5+
query: Query
6+
}
7+
8+
type Customer @mock {
9+
id: ID!
10+
name: String @mockfn(name: "LastName")
11+
email: String @mockfn(name: "Email")
12+
address: Address
13+
}
14+
15+
type Address {
16+
city: String @mockfn(name: "City")
17+
zip: String @mockfn(name: "Zip")
18+
}
19+
20+
type Query {
21+
customer(id: ID): Customer
22+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
query Customer($id: ID!) {
2+
customer(id: $id) {
3+
id
4+
name
5+
email
6+
address {
7+
city
8+
zip
9+
}
10+
}
11+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"endpoint": "api/misc"
3+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const fs = require("fs");
2+
const path = require("node:path");
3+
4+
const {
5+
deployAndRun,
6+
getTestDescription,
7+
} = require("../../../tests/gqltest.js");
8+
9+
testDescription = getTestDescription("snippets", __dirname);
10+
11+
const requestsFile = path.join(path.dirname(__dirname), "operations.graphql");
12+
const requests = fs.readFileSync(requestsFile, "utf8").toString();
13+
14+
describe(testDescription, function () {
15+
const tests = [
16+
{
17+
label: "customer",
18+
query: requests,
19+
operationName: "Customer",
20+
variables: {
21+
id: 1238,
22+
},
23+
expected: {
24+
customer: {
25+
id: "1238",
26+
name: "Baumbach",
27+
28+
address: {
29+
city: "New Schroeder",
30+
zip: "36897",
31+
},
32+
},
33+
},
34+
},
35+
];
36+
return deployAndRun(__dirname, tests);
37+
});

0 commit comments

Comments
 (0)