Skip to content
Snippets Groups Projects
Commit 6dfd4f47 authored by Tim Fechner's avatar Tim Fechner
Browse files

Refactor api module, introduce tornato bindings

parent 73d0a586
No related branches found
No related tags found
No related merge requests found
Pipeline #
......@@ -12,3 +12,17 @@ Issues and further documentation can be found there.
## Development
A complete list of the `Minion.data` json structure can be found [here](https://lab.it.hs-hannover.de/django/salt-observer/wikis/minion-data-structure) in the wiki.
```python
# get output of 'w' command of all 'tgt' minions
request('token', {'tgt': '*', 'fun': 'cmd.run', 'arg': 'w'})
# get all grains of 'tgt' minions
request('token', {'tgt': '*', 'fun': 'grains.items'})
# execute some state and apply custom pillars to it
request('token', {'tgt': '*', 'fun': 'state.sls', 'kwarg': {
'mods': 'name_of_state', 'pillar': {'some': 'pillar_data'}
}})
```
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from salt_observer.cherry import SaltCherrypyApi
from salt_observer.saltapis import SaltCherrypy, SaltTornado
class RestBackend(ModelBackend):
''' Authenticate against salt-api-permissions '''
def authenticate(self, username=None, password=None):
def authenticate(self, username=None, password=None, request=None):
try:
valid = SaltCherrypyApi.obtain_auth_token(username, password)
except:
valid = False
cherrypy_token = SaltCherrypy(username, password).token
tornado_token = SaltTornado(username, password).token
except Exception as e:
cherrypy_token = False
tornado_token = False
if valid:
if cherrypy_token and tornado_token:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
user = User.objects.create_user(username=username, email='', password=password)
request.session['salt_cherrypy_token'] = cherrypy_token
request.session['salt_tornado_token'] = tornado_token
return user
return None
from django import forms
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext, ugettext_lazy as _
......@@ -74,6 +75,31 @@ class LoginForm(AuthenticationForm):
username = forms.CharField(label='', max_length=255)
password = forms.CharField(label='', widget=forms.PasswordInput)
def clean(self):
'''
Overwriting this method to pass the current request down to the
backends via authenticate([...])
'''
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(
username=username,
password=password,
request=self.request
)
if self.user_cache is None:
raise forms.ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'username': self.username_field.verbose_name},
)
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
class MinionEditForm(MarkdownFormMixin):
class Meta:
......
from salt_observer.cherry import SaltCherrypyApi
from salt_observer.saltapis import SaltCherrypy
from getpass import getpass
......@@ -20,4 +20,4 @@ class ApiCommand(object):
else:
password = kwargs.get('password')
return SaltCherrypyApi(username, password)
return SaltCherrypy(username, password)
......@@ -26,9 +26,16 @@ DATABASES = {
# Salt observer configuration
SALT_API = {
'cherrypy': {
'host': 'localhost',
'port': 8989,
'protocol': 'http',
},
'tornado': {
'host': 'localhost',
'port': 8002,
'protocol': 'http'
}
}
# specify your salt network here to disable it in network visualization
......
......@@ -4,17 +4,33 @@ import requests
from getpass import getpass
class SaltCherrypyApi(object):
class AbstractApi(object):
'''
Defines an abstract api to inherit from.
You MUST specify a BASE_URL for your api to build a proper request url.
'''
BASE_URL = '{protocol}://{host}:{port}'.format(**settings.SALT_API)
BASE_URL = ''
def __init__(self, username, password):
''' Log in every time an instance is created '''
def __init__(self, username='', password='', token=''):
''' Set a token to work with '''
if not self.BASE_URL:
raise NotImplementedError('Please provide an BASE_URL')
if token:
self.token = token
else:
self.token = self.obtain_auth_token(username, password)
@classmethod
def obtain_auth_token(cls, username, password):
res = requests.post(cls.BASE_URL+'/login', headers={'Accept': 'application/json'}, data={
def request(self, method='get', resource='/', headers={}, data={}):
return getattr(requests, method)(
self.BASE_URL + resource,
headers=headers,
data=data
)
def obtain_auth_token(self, username, password):
res = self.request('post', '/login', headers={'Accept': 'application/json'}, data={
'username': username,
'password': password,
'eauth': 'pam'
......@@ -25,45 +41,34 @@ class SaltCherrypyApi(object):
return res.json().get('return')[0].get('token')
def request(self, data, api_point=''):
data.update({'client': 'local'})
return requests.post(
'{}/{}'.format(self.BASE_URL, api_point),
headers={
'Accept': 'application/json',
'X-Auth-Token': self.token
},
data=data
)
class SaltCherrypy(AbstractApi):
BASE_URL = '{protocol}://{host}:{port}'.format(**settings.SALT_API['cherrypy'])
def logout(self):
return requests.post(
self.BASE_URL+'/logout',
headers={
return self.request('post', '/logout', headers={
'Accept': 'application/json',
'X-Auth-Token': self.token
}
)
})
def get(self, module, target='*', api_args=[], api_kwargs={}):
return self.request({
return self.request(
'post',
data={
'client': 'local',
'fun': module,
'tgt': target,
'arg': api_args,
'kwarg': api_kwargs
}).json().get('return')[0]
# experimental:
# ---
#
# get output of 'w' command of all 'tgt' minions
# request('token', {'tgt': '*', 'fun': 'cmd.run', 'arg': 'w'})
#
# get all grains of 'tgt' minions
# request('token', {'tgt': '*', 'fun': 'grains.items'})
#
# execute some state and apply custom pillars to it
# request('token', {'tgt': '*', 'fun': 'state.sls', 'kwarg': {
# 'mods': 'name_of_state', 'pillar': {'some': 'pillar_data'}
# }})
},
headers={
'Accept': 'application/json',
'X-Auth-Token': self.token
}
).json().get('return')[0]
class SaltTornado(AbstractApi):
BASE_URL = '{protocol}://{host}:{port}'.format(**settings.SALT_API['tornado'])
......@@ -49,6 +49,12 @@ class Login(FormView):
login(self.request, form.get_user())
return super().form_valid(form, *args, **kwargs)
def get_form_kwargs(self, *args, **kwargs):
'''dirty hack to pass the current request down to the backends'''
kwargs = super().get_form_kwargs(*args, **kwargs)
kwargs['request'] = self.request
return kwargs
def get_success_url(self):
return self.request.GET.get('next', reverse_lazy('dashboard'))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment