Skip to content

SecretsAndNamespaces

Note: The following section is mostly related to the container-based jobs running in Kubernetes.

Secrets

It is not unusual for a job to require some credentials or access keys so that some protected resources can be accessed from within the job. Generally the values for such credentials or access keys should be kept secret, i.e. not part of the container itself, and even better not part of the request that creates the job itself. In order to support such protected values the job service offers the concept of "secrets".

Secret is a value that will be sourced from a secure opaque provider and exposed to the container running the job. The value is not exposed to the job service.

In the container-based jobs the secret is implemented using the "Secret" object available from kubernetes. Read more about kuberenetes secrets here.

Namespaces

Namespaces are closely related with the secrets, as the namespaces provide the isolation for different tenants. Read more about kubernetes namespaces here.

By default, each job runs in a namespace provided by the Platform. It is not possible to use secrets when the job runs in this namespace, because then the secret values might become compromised from other resources in this shared namespace. In order to use secrets, the job needs to run in a namespace provided by the caller. In this namespace either the owner or the job service itself will deploy secrets and those can be exposed to the jobs.

This document will refer to the namespace that is provided by the caller as the "user namespace".

As of 24-Mar-2022 it is only possible to specify the user namespace as the namespace of caller that creates the job. As a consequence the user namespace feature can only be used from applications that run within the Platform kubernetes cluster.

Existing secrets

Existing secret is a secret which already exists when the job is being started. It is owned by the maintainers of the user namespace. Populating the actual value is also the responsibility of the namespace owners. The user has to provide the secret name along with the job request.

Ad-hoc secrets

Ad-hoc secret is a secret which is created by the job service. The secret is created for a single job and its lifecycle is tied to it. There are two ways in which a secret can be referenced from a job. - External secret The value is populated from a secure provider (also called "backend") to which the kubernetes cluster has access. The user provides the backend type, resource name, and a key. Kubernetes extracts the value from this source using a custom object ExternalSecret and creates a regular Secret object based on that. Read more here about external secrets. - Internal secret The value is posted as part of the http request and is stored directly in kubernetes using a kubernetes object V1Secret and creates a regular Secret object based on that.

Exposing the secret value to the job

The actual secret value can be exposed to the job container in different ways. - Environment variable can be created (the user specifies the variable name) - File can be created and mounted to the container. The file name is provided by the user. The file will be available under /config folder in the container.

Example

The following example creates a job that runs in the caller namespace and exposes both types of secrets (existing secret adn ad-hoc internal secret) to the container in two ways - as an environment variable and a file.

=== "HTTP REST API"
    ```sh

    Body:
    {
        "runtime": {
            "type": "ContainerRuntimeSpec",
            "containers": [
                { 
                    "Image": "busybox",
                    "Command": ["/bin/sh", "-c", "printenv | grep MYSECRET; cat /config/mysecret.txt;"],
                    "Secrets": [
                        { 
                            "secretSource": { "type": "ExistingSecret", "secretName": "myexistingsecret", "item": "mysecretitem" },
                            "secretLink": { "type": "EnvironmentVariableSecret", "environmentVariableName": "MYSECRET" } 
                        },
                        { 
                            "secretSource": { "type": "ExistingSecret", "secretName": "myexistingsecret", "item": "mysecretitem" },
                            "secretLink": { "type": "FileSecret", "fileName": "mysecret.txt" } 
                        },
                        { 
                            "secretSource": { "type": "AdHocInternalSecret", "item": "mysecretitem" },
                            "secretLink": { "type": "EnvironmentVariableSecret", "environmentVariableName": "MYSECRET" } 
                        },
                        { 
                            "secretSource": { "type": "AdHocInternalSecret", "item": "mysecretitem" },
                            "secretLink": { "type": "FileSecret", "fileName": "mysecret.txt" } 
                        }
                    ]
                }
            ],
            "runInCallerNamespace": true
        }
    }

    Kubernetes token (by default stored in /var/run/secrets/kubernetes.io/serviceaccount/token) has to be sent in an Authorization header with K8S scheme - i.e. Authorization: K8S ey...
    ```

=== "C# SDK"
    ```csharp
        var job = await computeClient
            .CreateJob(projectId, "busybox", new[] { "/bin/sh", "-c", "printenv | grep MYSECRET; cat /config/secretfile.txt" }, 0.5f)
            .RunInCallerNamespace()
            .WithExistingSecretAsEnvironmentVariable("myexistingsecret", "mysecretitem", "MYSECRET")
            .WithExistingSecretAsFile("myexistingsecret", "mysecretitem", "secretfile.txt")
            .WithAdHocSecretAsEnvironmentVariable("mysecretitem", "MYSECRET")
            .WithAdHocSecretAsFile("mysecretitem", "secretfile.txt")
            .ExecuteAsync();
    ```