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
25 changes: 25 additions & 0 deletions rest/ibm-iam/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# IBM IAM Token

## Overview

Defines a field `Query.ibm_iam_token` that obtains an IBM Cloud IAM token.

This can be used in as the first step of a sequence to obtain a token for a subsequent execution
of an `@rest` field in the sequence.

An example (`Query.usage`) is provided of accessing the IBM Cloud billing usage endpoint using
a `@sequence` to fetch a token and then make the REST request.

The same technique can be used with any IAM system.

## Try it out

The schema must be deployed with the environment variable `STEPZEN_IBM_IAM_APIKEY` set
to an IBM Cloud API key, typically by a CI/CD workflow.

Then a request such as this can be executed, replacing `<<account ID>>` with an IBM Cloud account ID
that matches the IBM Cloud API key:

```
stepzen request '{usage(account:"<<account ID>>" month:"2025-01") }'
```
5 changes: 5 additions & 0 deletions rest/ibm-iam/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
configurationset:
- configuration:
endpoint: https://iam.cloud.ibm.com/identity/token
apikey: STEPZEN_IBM_IAM_APIKEY
name: ibm-iam
33 changes: 33 additions & 0 deletions rest/ibm-iam/ibm-iam.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
extend type Query {
"""
Obtain an IBM Cloud bearer token.

Uses the [IBM Cloud API Key](https://cloud.ibm.com/docs/account?topic=account-userapikey&interface=ui#userapikey)
or [service ID's API Key](https://cloud.ibm.com/docs/account?topic=account-serviceidapikeys&interface=ui)
to [generate an IAM Token](https://cloud.ibm.com/docs/account?topic=account-iamtoken_from_apikey#iamtoken_from_apikey)
"""
ibm_iam_token: Secret
@rest(
endpoint: "$endpoint"
method: POST
contenttype: "x-www-form-urlencoded"
postbody: """
grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={{ .Get "apikey"}}
"""
ecmascript: """
function transformREST(body) {
switch (status) {
case 200:
return body
case 401:
case 400: // returned for apikey not found
throw new Error('unauthorized');
default:
throw new Error('unknown error');
}
}
"""
setters: { path: "access_token" }
configuration: "ibm-iam"
)
}
48 changes: 48 additions & 0 deletions rest/ibm-iam/index.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
schema @sdl(files: ["ibm-iam.graphql"]) {
query: Query
}

"""
Example use of `Query.ibm_iam_token`.

First fetches a token and then executes a REST request using the token.
"""
type Query {
"""
IBM Cloud account usage.
"""
usage(
"""
IBM Cloud account ID.
"""
account: String!
"""
Billing month with format `yyyy-mm`
"""
month: String!
): JSON
@sequence(
steps: [
{ query: "ibm_iam_token" }
{
query: "_usage"
arguments: [
{ name: "token", field: "§0" }
{ name: "account", argument: "account" }
{ name: "month", argument: "month" }
]
}
]
)

"""
Fetch requesst against the usage endpoint.

https://cloud.ibm.com/apidocs/metering-reporting#get-account-usage
"""
_usage(token: Secret!, account: String!, month: String!): JSON
@rest(
endpoint: "https://billing.cloud.ibm.com/v4/accounts/$account/usage/$month"
headers: { name: "Authorization", value: "Bearer $token" }
)
}
3 changes: 3 additions & 0 deletions rest/ibm-iam/stepzen.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"endpoint": "api/miscellaneous"
}
11 changes: 11 additions & 0 deletions rest/ibm-iam/tests/Test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const {
deployAndRun,
getTestDescription,
} = require("../../../tests/gqltest.js");

testDescription = getTestDescription("snippets", __dirname);

describe(testDescription, function () {
const tests = [];
return deployAndRun(__dirname, tests);
});