Skip to content

Commit

Permalink
Add support for AnsibleTower token use
Browse files Browse the repository at this point in the history
Automatic username lookup when using token
Ability to still set username in settings
Updated inventory sync examples
Updated README for token use
  • Loading branch information
mshriver authored and JacobCallahan committed Sep 4, 2020
1 parent a36f547 commit 198f8f0
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 13 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ Broker can also be ran outside of its base directory. In order to do so, specify
`BROKER_DIRECTORY` envronment variable.
```BROKER_DIRECTORY=/home/jake/Programming/broker/ broker inventory```

# Configuration
The broker_settings.yaml file is used, through DynaConf, to set configuration values for broker's interaction with its 'providers'.

DynaConf integration provides support for setting environment variables to override any settings from the yaml file.

An environment variable override would take the form of: `DYNACONF_AnsibleTower__base_url="https://my.ansibletower.instance.com"`. Note the use of double underscores to model nested maps in yaml.

For the AnsibleTower provider, authentication can be achieved either through setting a username and password, or through a token (Personal Access Token in Tower).

A username can still be provided when using a token to authenticate. This user will be used for inventory sync (examples below). This may be helpful for AnsibleTower administrators who would like to use their own token to authenticate, but want to set a different user in configuration for checking inventory.

# Usage
**Checking out a VM**
```
Expand Down Expand Up @@ -54,6 +65,10 @@ To sync your inventory from a supported provider, use the `--sync` option.
```
broker inventory --sync AnsibleTower
```
To sync inventory for a specific user, use the following syntax with `--sync`.
```
broker inventory --sync AnsibleTower:<username>
```

**Extending your VM lease time***
Providers supporting extending a VM's lease time make that functionality available through the `extend` subcommand.
Expand Down
46 changes: 35 additions & 11 deletions broker/providers/ansible_tower.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import inspect
import json
import sys
from broker.settings import settings
from logzero import logger

Expand All @@ -13,8 +14,9 @@
from broker import helpers

AT_URL = settings.ANSIBLETOWER.base_url
UNAME = settings.ANSIBLETOWER.username
PWORD = settings.ANSIBLETOWER.password
UNAME = settings.ANSIBLETOWER.get("username")
PWORD = settings.ANSIBLETOWER.get("password")
TOKEN = settings.ANSIBLETOWER.get("token")
RELEASE_WORKFLOW = settings.ANSIBLETOWER.release_workflow
EXTEND_WORKFLOW = settings.ANSIBLETOWER.extend_workflow
AT_TIMEOUT = settings.ANSIBLETOWER.workflow_timeout
Expand All @@ -25,14 +27,36 @@ def __init__(self, **kwargs):
self._construct_params = []
config = kwargs.get("config", awxkit.config)
config.base_url = AT_URL
config.credentials = {"default": {"username": UNAME, "password": PWORD}}
config.use_sessions = True
if "root" in kwargs:
root = kwargs.get("root")
else:
root = awxkit.api.Api()
root.load_session().get()
self.v2 = root.available_versions.v2.get()
# Prefer token if its set, otherwise use username/password
# auth paths for the API taken from:
# https://github.com/ansible/awx/blob/ddb6c5d0cce60779be279b702a15a2fddfcd0724/awxkit/awxkit/cli/client.py#L85-L94
# unit test mock structure means the root API instance can't be loaded on the same line
root = kwargs.get("root")
if root is None:
root = awxkit.api.Api() # support mock stub for unit tests
if TOKEN:
logger.info("Using token authentication")
config.token = TOKEN
root.connection.login(username=None, password=None, token=TOKEN, auth_type='Bearer')
versions = root.get().available_versions
try:
# lookup the user that authenticated with the token
# If a username was specified in config, use that instead
my_username = UNAME or versions.v2.get().me.get().results[0].username
except (IndexError, AttributeError):
# lookup failed for whatever reason
logger.error("Failed to lookup a username for the given token, please check credentials")
sys.exit()
else: # dynaconf validators should have checked that either token or password was provided
logger.info("Using username and password authentication")
config.credentials = {"default": {"username": UNAME, "password": PWORD}}
config.use_sessions = True
root.load_session().get()
versions = root.available_versions
my_username = UNAME
self.v2 = versions.v2.get()
self.username = my_username


def _host_release(self):
caller_host = inspect.stack()[1][0].f_locals["host"]
Expand Down Expand Up @@ -192,7 +216,7 @@ def exec_workflow(self, **kwargs):

def get_inventory(self, user=None):
"""Compile a list of hosts based on any inventory a user's name is mentioned"""
user = user or UNAME
user = user or self.username
invs = [
inv
for inv in self.v2.inventory.get(page_size=100).results
Expand Down
6 changes: 4 additions & 2 deletions broker/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
settings_path = BROKER_DIRECTORY.joinpath("broker_settings.yaml")
must_exist = [
"ANSIBLETOWER.base_url",
"ANSIBLETOWER.username",
"ANSIBLETOWER.password",
"NICKS",
"HOST_PASSWORD",
]
Expand All @@ -27,8 +25,12 @@
Validator("ANSIBLETOWER.extend_workflow", default="extend-vm"),
Validator("ANSIBLETOWER.workflow_timeout", is_type_of=int, default=3600),
Validator("HOST_USERNAME", default="root"),
# Validator combination for username+password or token
((Validator("ANSIBLETOWER.username", must_exist=True) & Validator("ANSIBLETOWER.password", must_exist=True))
| Validator("ANSIBLETOWER.token", must_exist=True))
]
settings = Dynaconf(settings_file=str(settings_path), validators=validators,)

try:
settings.validators.validate()
except ValidationError as err:
Expand Down
2 changes: 2 additions & 0 deletions broker_settings.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ host_password: "<password>"
# Provider settings
AnsibleTower:
base_url: "https://<ansible tower host>/"
# Username AND password, OR an OAUTH token can be used for authentication
username: "<username>"
password: "<plain text password>"
token: "<AT personal access token>"
release_workflow: "remove-vm"
extend_workflow: "extend-vm"
workflow_timeout: 3600
Expand Down

0 comments on commit 198f8f0

Please sign in to comment.