Using App Tokens

This section describes how to use application tokens to make API calls and automate workload deployment using APC from an Apcera job.

App Token is an advanced feature that requires familiarity with Apcera policy, job creation, and service binding.

Introducing App Token

The application token (App Token) feature enables jobs to obtain an access token to make API calls or run APC commands (if installed) without having to authenticate against an external identity system, such as LDAP or Google. This lets you create a job that automates the Apcera job creation and deployment process using systems such as Jenkins.

Previously token issuance (permit issue) was exclusive to the auth::/ realm for generating user tokens. With App Token you can assert the permit issue claim on the job::/ realm with a matching FQN, permitting a job to be issued a token. Once the job has a token, the job can make API calls or run APC commands (after installing APC).

To get started using App Token, check out the App Token tutorial.

Requirements

HTTPS routing

To use the App Token feature, your cluster must be configured for HTTPS. The semantic pipeline that mediates API requests from your job requires an HTTPS connection to the API server so it can transmit the app token securely.

To enable HTTPS for your cluster, see configuring HTTPS for EE or configuring HTTPS for CE.

Semantic pipeline

To use app tokens you must bind your application to the Apcera-provided HTTP service type and gateway. This service type includes a semantic pipeline that mediates HTTP traffic between your app and the cluster's API server. It intercepts HTTP requests from your app to the cluster's API server, inserts the app token into the "Authorization" header, and relays the request over secure connection to the API server.

Alt text

HTTPS is not currently supported between jobs and the HTTP semantic pipelines. For this reason your app must use HTTP when making calls to the cluster's API server, or running APC commands. The modified request made by the semantic pipeline to the API server is always made over a secure connection, however, as illustrated above.

Policy

You must author app token policy to issue an app token to a job, and to grant the job resource permissions as you would a user.

API calls

Once policy is in place to issue your job an app token, your job can make API calls freely without having to manually include a token in each request. Note the following:

  • API calls must be made using http:// protocol. The semantic pipeline that inserts the app token into the request only works with HTTP connections.
  • App tokens are currently not supported for API calls that contact the Auth Server. These include API calls related to policy, such as PUT /v1/policy.

Workflow

The workflow for using app tokens is as follows:

  1. Author app token policy to issue a JSON web token (JWT) to the target job.
  2. Author policy permissions for the target job to act on desired resources.
  3. Bind the target job to the HTTP service, giving you a semantic pipeline.
  4. Configure your application to make calls to the API Server.

App Token policy

To implement App Token, you must first author policy that issues an access token to the target job.

Permit issue on job

To issue an access token to a job, you assert the permit issue claim on the job's FQN. For example, the following policy permits a token to be issued to the job with the FQN job::/sandbox/user::myjob:

on job::/sandbox/user::myjob { 
  { permit issue }
}

When issuing the token, you must use the full FQN including the local name for the policy realm declaration. You cannot issue a token on a namespace (job::/sandbox/user, for example). Just like a user token can only be issued to 1 user, an app token can only be issued to a single job.

Token timeout considerations

The permit issue is the key to allowing the job to get an app token. The tokenTimeout claim is optional and specifies how long the access token is valid before it must be renewed. If not specified, the default token timeout of 1800s (30 minutes) is used.

If you want a different timeout interval for the token, you can set it as follows. You may want shorter renewal times if you have sensitive apps and longer renewals to avoid the time it takes to verify policy and re-issue a token.

on job::/sandbox/user::myjob { 
   { permit issue }
   { tokenTimeout "3600s"
}

Default namespace considerations

The name assigned to the token is of the form job::/name/space::app-name. In addition, the authtype is AppAuth. Thus, to author policy that assign a default namespace you can do the following:

on auth::/ {
  if (auth_server@apcera.me->name beginsWith "job::/foo")
  { 
    defaultNamespace "sandbox/foo" 
  }
}

Or:

on auth::/ {
  if (auth_server@apcera.me->authType == "AppAuth")
  { 
    defaultNamespacePrefix "sandbox/" 
  }
}

Alternatively you can set the default namespace on the job:

on job::/sandbox/user::myjob {
    { permit issue } 
    { tokenTimeout "3600s" }
    { defaultNamespace "sandbox/foo" }
}

When APC calls the API Server to get the default namespace using an app token and there is no policy covering it, the default namespace becomes the system default namespace prefix plus the job’s namespace::localname. This can be avoided by either 1) Setting a default for the job using an app token via policy, or 2) Explicitly issuing the apc namespace command.

Job permissions policy

The principal in the token is of the form job::/name/space::app-name. Once the token is issued to the job, you can write policy as follows to permit the job (user) to take action in the cluster.

on cluster::/ {
  if (auth_server@apcera.me->name == "job::/name/space::app-name")
	{ permit read }
}
on job::/ {
  if (auth_server@apcera.me->name == "job::/name/space::app-name")
    { permit create, read, update, delete }
}
etc.

Bind job to HTTP service

App Token requires you to use the Apcera-provided HTTP service type and gateway. This service type includes a semantic pipeline that mediates HTTP traffic between the job and the cluster's API server. Specifically, the semantic pipeline obtains an application token from the cluster's Authentication server, and inserts it into the "Authorization" header of each request to the API server. The semantic pipeline then connects over HTTPS to the API server.

To bind the target job to the HTTP service using APC:

apc service bind /apcera::http --job job::/name/space::app-name

For example, assuming you have targeted your cluster and logged in, and created job my-app-token-job, as follows:

apc target CLUSTER-NAME
apc login ...

apc app create my-app-token-job

Then to bind the job to the HTTP service:

apc service bind /apcera::http -j my-app-token-job

apc app start my-app-token-job

By binding the target job to the HTTP service, the connection is brokered by a HTTP semantic pipeline. The semantic pipeline understands the HTTP protocol and acts as a proxy between the job and the service. When the job makes an HTTP request to the cluster's API server (by making an API call or running an APC command) the semantic pipeline automatically inserts the app token into the request's "Authorization" HTTP header.

Using APC with app token

Once an app token is issued using policy and your job is bound to the HTTP service, your job can install and configure APC for your cluster. Once APC is installed, you must target your cluster over HTTP with apc target http://<cluster-name>.<domain> and login using the --app-auth parameter, for example:

apc target http://cluster-name.domain
apc login --app-auth

You also need to set the APC_HOME environment variable on the job to a writable directory. The easiest way is to set it to the app's current directory, for example:

APC_HOME=`pwd`

Note the following:

  • You must target your cluster explicitly using HTTP (for example, apc target http://<your-cluster>) since the HTTP semantic pipeline that mediates the connection does not support HTTPS.
  • You can not run APC commands that communicate with the cluster Auth server, including commands for working with policy (apc policy export, for example).

Set APC_HOME env var

When running APC in a job you need to set APC_HOME to a writable directory. The easiest way is to set it to the current directory the job runs in, for example: APC_HOME=`pwd`. This sets the APC_HOME environment var to the output of the pwd command (print working directory).

Example Bash script that uses APC

The following Bash script downloads APC from your cluster, targets and logs in to the cluster, and runs apc list jobs --namespace / to list all jobs.

To use this script:

  1. Copy the following code into a file named bash_start.sh:

     # Set your target cluster name and domain
     export target=your-cluster.apcera-platform.io
    
     # Set APC_HOME environment variable
     export APC_HOME=`pwd`
        
     # Download APC from target cluster
     wget http://api.$target/v1/apc/download/linux_amd64/apc.zip
     unzip apc.zip
     rm apc.zip
    
     # Target cluster over HTTP and login with --app-auth parameter
     ./apc target http://$target
     ./apc login --app-auth
    
     # List all jobs the app has permission to read
     ./apc job list --namespace /
    
     # Keep process alive so Health Manager doesn't try to restart app.
     tail -f
    
  2. Edit the target variable in bash_start.sh to point to your cluster. Save your changes to bash_start.sh.
  3. Deploy the Bash app to your cluster:

     apc app create apptoken-test --disable-routes --batch
    
  4. Bind the app to the HTTP service:

     apc service bind /apcera::http --job apptoken-test
    
  5. Add the following policy that issues a token to the app and gives it permissions to read all jobs on the cluster. Change the job's namespace (/sandbox/admin) in each policy rule to match your development environment.

     job::/sandbox/admin::apptoken-test {
         {permit issue}
     }
        
     on job::/ {
       if (auth_server@apcera.me->name == "job::/sandbox/admin::apptoken-test")
         { permit read }
     }        
    
  6. Start the application.

     apc app start apptoken-test
    
  7. View the app logs:

     apc app logs apptoken-test --lines 1000
    

    Logs should show the output of the Bash app downloading APC, targeting and logging to the cluster, and listing jobs, e.g.:

     [stderr][80c3f684] --2016-09-14 20:31:47--  http://api.example.com/v1/apc/download/linux_amd64/apc.zip
     [stderr][80c3f684] Resolving api.example.com (api.example.com)... 54.191.20.237, 52.25.247.200, 54.148.35.105
     [stderr][80c3f684] Connecting to api.example.com (api.example.com)|54.191.20.237|:80... connected.
     [stderr][80c3f684] HTTP request sent, awaiting response... 200 OK
     [stderr][80c3f684] Length: 6372896 (6.1M) [application/zip]
     [stderr][80c3f684] Saving to: 'apc.zip'
     [stderr][80c3f684]      0K .......... .......... .......... .......... ..........  0%!M(MISSING) 1s
     ...
     [stderr][80c3f684]   6200K .......... .......... ...                             100%!M(MISSING)=1.0s
     [stderr][80c3f684] 2016-09-14 20:31:48 (5.83 MB/s) - 'apc.zip' saved [6372896/6372896]
     [stdout][80c3f684] Archive:  apc.zip
     [stdout][80c3f684]   inflating: apc                     
     [stdout][80c3f684] Note: connections over HTTP are insecure and may leak secure information.
     [stdout][80c3f684] Targeted [http://example.com]
     [stdout][80c3f684] Connecting to http://example.com...
     [stdout][80c3f684] Login successful for 
     [stdout][80c3f684] Working in "/"
     [stdout][80c3f684] +-------------+---------+--------------------------+---------+-----------+
     [stdout][80c3f684] | Name        | Type    | Namespace                | Status  | Instances |
     [stdout][80c3f684] +-------------+---------+--------------------------+---------+-----------+
     [stdout][80c3f684] | generic     | gateway | /apcera/service-gateways | started | 1/1       |
     [stdout][80c3f684] | gnatsd      | gateway | /apcera/service-gateways | started | 1/1       |
     [stdout][80c3f684] | http        | gateway | /apcera/service-gateways | started | 1/1       |
     [stdout][80c3f684] | ipm         | gateway | /apcera/service-gateways | started | 1/1       |
     ...
    

Troubleshooting

If you receive the error "Header must have a preamble and a token separated by a space," this can indicate 1 of 2 problems. First, it can mean that you didn’t bind the job to the HTTP service (specifically, the semantic pipeline that is created automatically when you bind the job to the HTTP service). Second, it can mean that you did not author policy to permit issue on the job. To remedy the issue, make sure you authored policy and bound the job to the HTTP service.

When using apc login --app-auth to use App Token, apc initializes its environment using an unsigned token. This token is a placeholder used for transport purposes in the Apcera Platform. It is not used for authentication or authorization. The Semantic Pipeline will acquire an authenticated token for the job provided that the job has permit issue from policy. It is the intended behavior that the same placeholder token is stored in each .apc file.