Skip to main content
Version: v1alpha1

Nine Self Service API

The Nine Self Service API allows you to provision various services using a HTTP REST API. The API is based on Kubernetes, meaning existing tooling can be used to interact with it.

Authentication

To authenticate to the API, you need to create an API Service Account using nctl or in Cockpit in the API tab under the account settings.

nctl auth login
nctl create asa cicd
nctl get asa cicd --print-credentials

The API service account makes use of OAuth 2.0 client credentials, meaning you get a client_id and client_secret that you can use to get a short lived access token.

curl --location --request POST 'https://auth.nine.ch/auth/realms/pub/protocol/openid-connect/token' \
--data-urlencode 'client_id=asa-example-6baa969-1891dc6' \
--data-urlencode 'client_secret=examplesecret' \
--data-urlencode 'grant_type=client_credentials'

You can also use nctl to get a fresh access token no matter if you are using your personal account or a service account:

nctl auth print-access-token

The access token has to be sent to the API with each request using the Authorization: Bearer <token> HTTP header.

Namespace

All the resources you can create reside in a namespace allocated for your Cockpit account. This means with all requests you will have to specify the namespace of the resource you are interacting with. The namespace equals to the account name that is displayed under Recently Used in Cockpit. The service account you previously created just has access to resources in the same namespace it resides in.

Making a first request

To verify that the token works as expected, you can try to issue the following request using curl. If you get the following reply, the authentication works:

$ curl https://nineapis.ch/api/ -H "Authorization: Bearer <token>"
{
"kind": "APIVersions",
"versions": [
"v1"
],
...
}

Creating a resource with curl

Now that we are authenticated with the API, let's create a first resource with it. Note that a lot of resources that can be created on the API incur costs, so be careful when testing your integration. Here we create an object storage bucket, which by itself is free as long as no data is uploaded to it.

$ curl -X POST https://nineapis.ch/apis/storage.nine.ch/v1alpha1/namespaces/<your namespace>/buckets \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
--request POST \
--data '{
"kind": "Bucket",
"apiVersion": "storage.nine.ch/v1alpha1",
"metadata": {
"name": "hello-api"
},
"spec": {
"forProvider": {
"encryption": true,
"location": "nine-es34"
}
}
}'

Using kubectl

Besides using any HTTP client, the API can also be interacted with using the command line tool kubectl. If you are logged into nctl with your personal account, you can just start using kubectl.

To use it with an API service account, you can get the kubeconfig like this:

nctl get apiserviceaccount example --print-kubeconfig

Then access resources by their fully qualified name.

$ kubectl --context nineapis.ch get buckets.storage.nine.ch
NAME SYNCED READY AGE
hello-api True True 10m

Resource Status

After you create a resource using the API, how do you know it is ready? This is where the status.conditions field comes in. It represents the current state of that resource. For example, when getting the status of a Bucket it might look something like this:

"status": {
"conditions": [
{
"lastTransitionTime": "2023-03-05T08:25:41Z",
"reason": "ReconcileSuccess",
"status": "True",
"type": "Synced"
},
{
"lastTransitionTime": "2023-03-05T08:25:41Z",
"reason": "Available",
"status": "True",
"type": "Ready"
}
]
}

For knowing whether a resource is ready to use, the relevant condition is the one with type: Ready. This one indicates whether the backend resource is ready. The other important field within the condition is the reason. The following reasons exist:

  • Available: The resource is available for use.
  • Unavailable: The resource is currently unhealthy, making it temporarily unavailable.
  • Creating: The resource is currently being created.
  • Deleting The resource is currently being deleted.

For catching errors during the creation process, one should look for the type: Synced. There is a reason field, same as with the ready status. Here we simply have these reasons:

  • ReconcileSuccess: The resource has at successfully reconciled at least once. Note that this does not mean it is ready to use.
  • ReconcileError: The resource experienced an error during reconciliation. In this case, have a look at the message field to tell you more about why it errored.

Connection Secret

For resources which need credentials to access them after creation, there is a system in place to automatically write those credentials to a normal Kubernetes secret. For example, when creating a BucketUser it generates an S3 access key and secret which can then be used to authenticate against the object storage. As a user you can simply tell the BucketUser where to write those credentials by using the spec.writeConnectionSecretToRef field.

"spec": {
"writeConnectionSecretToRef": {
"name": "some-secret",
"namespace": "<your namespace>"
}
}

In this case, the credentials would end up in the secret a-secret within your organizations namespace.

Deletion Protection

The deletion protection feature helps prevent accidental deletion of the API resources listed in this documentation. This is an additional security measure intended to protect production applications and related data.

To prevent a resource from being deleted, you can add the nine.ch/deletion-protection: "true" annotation. As long as this annotation exists, the resource can not be deleted. Please make sure you use "true" to activate this feature. For example, to protect your projects.management.nine.ch named foo, you can use the following command:

kubectl annotate projects.management.nine.ch foo nine.ch/deletion-protection=true

To test if the annotation prevents an accidental deletion you can use the --dry-run=server option of kubectl:

kubectl delete --dry-run=server projects.management.nine.ch foo

Error from server (Forbidden): admission webhook
"deletion-protection.nine-controllers.nine.ch" denied the request: preventing
deletion because of nine.ch/deletion-protection annotation

To disable the deletion protection, you can either remove the annotation completely or use the value "false":

kubectl annotate --overwrite projects.management.nine.ch foo nine.ch/deletion-protection=false

An additional deletion test should confirm feature deactivation:

kubectl delete --dry-run=server projects.management.nine.ch foo

project.management.nine.ch "nine-staging-foo" deleted (server dry run)

Please note that using a value other than "true" or "false" will result in an error when modifying the resource.

Authentication

Send the token as: Authorization: Bearer <token>.

Security Scheme Type:

http

HTTP Authorization Scheme:

bearer

Bearer format:

JWT