Authenticating Open Source DC/OS with Third Party Services
I’ve recently started using the open-source version of DC/OS to deploy Docker containers and I couldn’t be happier with the results.
However, the most mind-boggling part of the entire setup was getting my company’s third-party Jenkins cluster to authenticate with DC/OS in an automated fashion.
Open-source DC/OS utilizes OAuth to authenticate your GitHub, Gmail, or Microsoft account with your DC/OS cluster. There’s documentation provided that walks you through how to create API tokens. But there are two problems with this workflow:
- The API token expires in five days
- Generating a new API token requires re-logging into your DC/OS cluster, which requires opening a browser to complete the OAuth flow
There is no official way to authenticate your DC/OS cluster with a third party service (such as Jenkins) in an automated fashion. So here’s how I managed to do it.
WARNING: This is a temporary workaround until more robust authentication features are rolled out for open-source DC/OS.
I’m running on the following specs although these instructions can be tweaked to work on any platform.
- CentOS 7.2
- Open-Source DC/OS 1.8
Step 1: Retrieve your DC/OS Cluster’s Master Secret
- SSH into one of your DC/OS master nodes
- Grab the contents of the following file:
cat /var/lib/dcos/dcos-oauth/auth-token-secret
WARNING: KEEP THIS SECRET SAFE. It can provide full-blown access to your DC/OS cluster.
Step 2: Generate a JSON Web Token
We’re going to use our Cluster’s Master Secret to generate a JWT for use by our third-party service (in our case, Jenkins).
I’m using Python in this example to generate the JWT. However, you’re free to use any library of your choice.
Install some python-related libraries (CentOS-specific instructions):
sudo yum -y install python-devel python-pip libxslt-devel libffi-devel openssl-devel
sudo pip install --upgrade pip
sudo pip install PyJWT
sudo pip install cryptography
Create a Python script (i.e. generate_dcos_token.py):
import jwt
import time
from datetime import datetime
from datetime import timedeltaexpTime = time.time() + (3600 * 876000)token = jwt.encode({'exp':expTime, 'uid': 'user@somewhere.com'}, '<CLUSTER_SECRET>', algorithm='HS256')
print token
IMPORTANT:
- Replace
<CLUSTER_SECRET>
with your Cluster's Master Secret - Replace
user@somewhere.com
with your DCOS user's username (most likely an email address) - Change
expTime
to a UNIX timestamp reflecting the date you'd like your token to expire - I’m setting the token to expire in 100 years in this example [NOT RECOMMENDED]
- A better workflow would probably be to setup your CI system to automatically generate a new token every few days
Run the python script and save the JWT token that the script prints out to your console:
python ./generate_dcos_token.py
Step 3: Confirm the JWT works
Run the following command to confirm the JWT token works
curl -X GET <DCOS_CLUSTER_URL>/acs/api/v1/users -H "Authorization: token=<JWT>"
IMPORTANT:
- Replace
<JWT>
with your newly generated JWT token - Replace
<DCOS_CLUSTER_URL
with your DCOS Master Cluster’s endpoint
Step 4: Use the JWT in your CI
In our case, we’re using an external Jenkins cluster to execute Marathon deployments. To do this, we added the JWT to Jenkins as a Secret Text
Credential for use with the Jenkins Marathon Plugin:
Finito!
You are now able to programmatically generate API tokens for open-source DC/OS, bypassing the need for manual intervention!