mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-22 22:03:54 +03:00
* Renamed udsProxy to udsproxy
* Woring first version proxy * Added basic sample config file for udsproxy * Added daemonize example for udsproxy Fixed os manager treatment of ready
This commit is contained in:
parent
d42482b6c3
commit
09a49a1cb2
@ -224,6 +224,7 @@ class Actor(Handler):
|
||||
try:
|
||||
res = service.getInstance().osmanager().process(service, message, data, options={'scramble': False})
|
||||
except Exception as e:
|
||||
logger.exception("Exception processing from OS Manager")
|
||||
return Actor.result(six.text_type(e), ERR_OSMANAGER_ERROR)
|
||||
|
||||
return Actor.result(res)
|
||||
|
@ -98,7 +98,7 @@ class Client(Handler):
|
||||
logger.debug("Client args for GET: {0}".format(self._args))
|
||||
|
||||
if len(self._args) == 0: # Gets version
|
||||
url = self._request.build_absolute_uri(reverse('ClientDownload'))
|
||||
url = self._request.build_absolute_uri(reverse('uds.web.views.client_downloads'))
|
||||
return Client.result({
|
||||
'availableVersion': CLIENT_VERSION,
|
||||
'requiredVersion': REQUIRED_CLIENT_VERSION,
|
||||
|
@ -51,7 +51,7 @@ import requests
|
||||
import json
|
||||
import logging
|
||||
|
||||
__updated__ = '2017-01-19'
|
||||
__updated__ = '2017-01-20'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -360,7 +360,10 @@ class UserServiceManager(object):
|
||||
UserServiceOpChecker.makeUnique(uService, ui, state)
|
||||
return False
|
||||
|
||||
def notifyPreconnect(self, uService, userName, protocol, proxy=None):
|
||||
def notifyPreconnect(self, uService, userName, protocol):
|
||||
|
||||
proxy = uService.deployed_service.proxy
|
||||
|
||||
url = uService.getCommsUrl()
|
||||
if url is None:
|
||||
logger.debug('No notification is made because agent does not supports notifications')
|
||||
@ -371,25 +374,22 @@ class UserServiceManager(object):
|
||||
try:
|
||||
data = {'user': userName, 'protocol': protocol}
|
||||
if proxy is not None:
|
||||
data = {
|
||||
'data': data,
|
||||
'url': url
|
||||
}
|
||||
|
||||
url = proxy.url
|
||||
|
||||
r = requests.post(url,
|
||||
data=json.dumps(data),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
timeout=2)
|
||||
proxy.doProxyRequest(url=url, data=data, timeout=2)
|
||||
else:
|
||||
r = requests.post(url,
|
||||
data=json.dumps(data),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
timeout=2)
|
||||
r = json.loads(r.content)
|
||||
logger.debug('Sent pre connection to client using {}: {}'.format(url, r))
|
||||
# In fact we ignore result right now
|
||||
except Exception as e:
|
||||
logger.info('preConnection failed: {}. Check connection on destination machine: {}'.format(e, url))
|
||||
|
||||
def checkUuid(self, uService, proxy=None):
|
||||
def checkUuid(self, uService):
|
||||
|
||||
proxy = uService.deployed_service.proxy
|
||||
|
||||
url = uService.getCommsUrl()
|
||||
|
||||
@ -404,13 +404,7 @@ class UserServiceManager(object):
|
||||
|
||||
try:
|
||||
if proxy is not None:
|
||||
r = requests.post(
|
||||
proxy.url,
|
||||
data=json.dumps({'url': url}),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
timeout=5
|
||||
)
|
||||
proxy.doProxyRequest(url=url, data=None, timeout=5)
|
||||
else:
|
||||
r = requests.get(
|
||||
url,
|
||||
@ -431,10 +425,12 @@ class UserServiceManager(object):
|
||||
|
||||
return True
|
||||
|
||||
def sendScript(self, uService, script, proxy=None):
|
||||
def sendScript(self, uService, script):
|
||||
'''
|
||||
If allowed, send script to user service
|
||||
'''
|
||||
proxy = uService.deployed_service.proxy
|
||||
|
||||
# logger.debug('Senging script: {}'.format(script))
|
||||
url = uService.getCommsUrl()
|
||||
if url is None:
|
||||
@ -445,20 +441,15 @@ class UserServiceManager(object):
|
||||
try:
|
||||
data = {'script': script}
|
||||
if proxy is not None:
|
||||
data = {
|
||||
'data': data,
|
||||
'url': url
|
||||
}
|
||||
|
||||
url = proxy.url
|
||||
|
||||
r = requests.post(
|
||||
url,
|
||||
data=json.dumps(data),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
timeout=5
|
||||
)
|
||||
proxy.doProxyRequest(url=url, data=data, timeout=5)
|
||||
else:
|
||||
r = requests.post(
|
||||
url,
|
||||
data=json.dumps(data),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
timeout=5
|
||||
)
|
||||
r = json.loads(r.content)
|
||||
logger.debug('Sent script to client using {}: {}'.format(url, r))
|
||||
# In fact we ignore result right now
|
||||
|
@ -42,7 +42,7 @@ from uds.core.util import connection
|
||||
import six
|
||||
import logging
|
||||
|
||||
__updated__ = '2017-01-19'
|
||||
__updated__ = '2017-01-20'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -108,10 +108,13 @@ class Transport(Module):
|
||||
'''
|
||||
pass
|
||||
|
||||
def testServer(self, userService, ip, port):
|
||||
def testServer(self, userService, ip, port, timeout=4):
|
||||
# TODO: Add Proxy support here
|
||||
# GET URL = proxy.../testService?ip=xxxxx&port=yyy&timeout=zzzz
|
||||
return connection.testServer(ip, six.text_type(port))
|
||||
proxy = userService.deployed_service.proxy
|
||||
if proxy is not None:
|
||||
return proxy.doTestServer(ip, port, timeout)
|
||||
return connection.testServer(ip, six.text_type(port), timeout)
|
||||
|
||||
|
||||
def isAvailableFor(self, userService, ip):
|
||||
|
@ -37,9 +37,9 @@ from django.db import models
|
||||
|
||||
from uds.models.UUIDModel import UUIDModel
|
||||
from uds.models.Tag import TaggingMixin
|
||||
from uds.models.Util import getSqlDatetime
|
||||
from django.db.models import signals
|
||||
|
||||
import requests
|
||||
import json
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -63,5 +63,49 @@ class Proxy(UUIDModel, TaggingMixin):
|
||||
db_table = 'uds_proxies'
|
||||
app_label = 'uds'
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return 'http{}://{}:{}'.format('s' if self.ssl is True else '', self.host, self.port)
|
||||
|
||||
@property
|
||||
def proxyRequestUrl(self):
|
||||
return self.url + "/proxyRequest"
|
||||
|
||||
@property
|
||||
def testServerUrl(self):
|
||||
return self.url + "/testServer"
|
||||
|
||||
def doProxyRequest(self, url, data=None, timeout=5):
|
||||
d = {
|
||||
'url': url
|
||||
}
|
||||
if data is not None:
|
||||
d['data'] = data
|
||||
|
||||
return requests.post(
|
||||
self.proxyRequestUrl,
|
||||
data=json.dumps(d),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
timeout=timeout
|
||||
)
|
||||
|
||||
|
||||
def doTestServer(self, ip, port, timeout=5):
|
||||
try:
|
||||
url = self.testServerUrl + '?host={}&port={}&timeout={}'.format(ip, port, timeout)
|
||||
r = requests.get(
|
||||
url,
|
||||
timeout=timeout + 1
|
||||
)
|
||||
if r.status_code == 302: # Proxy returns "Found" for a success test
|
||||
return True
|
||||
# Else returns 404
|
||||
except Exception:
|
||||
logger.exception("Getting service state through proxy")
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return 'Proxy {} on {}:{} '.format(self.name, self.host, self.port)
|
||||
|
@ -145,6 +145,12 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
notifyReady = False
|
||||
doRemove = False
|
||||
state = userService.os_state
|
||||
if msg in ('ready', 'ip'):
|
||||
if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information..
|
||||
data = {
|
||||
'ips': [v.split('=') for v in data.split(',')],
|
||||
'hostname': userService.friendly_name
|
||||
}
|
||||
|
||||
# Old "info" state, will be removed in a near future
|
||||
if msg == "info":
|
||||
@ -166,11 +172,6 @@ class LinuxOsManager(osmanagers.OSManager):
|
||||
doRemove = True
|
||||
elif msg == "ip":
|
||||
# This ocurss on main loop inside machine, so userService is usable
|
||||
if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information..
|
||||
data = {
|
||||
'ips': [v.split('=') for v in data.split(',')],
|
||||
'hostname': userService.friendly_name
|
||||
}
|
||||
state = State.USABLE
|
||||
self.notifyIp(userService.unique_id, userService, data)
|
||||
elif msg == "ready":
|
||||
|
@ -149,6 +149,14 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
* msg = ready, data = None, Informs machine ready to be used
|
||||
'''
|
||||
logger.info("Invoked WindowsOsManager for {0} with params: {1},{2}".format(userService, msg, data))
|
||||
|
||||
if msg in ('ready', 'ip'):
|
||||
if not isinstance(data, dict): # Old actors, previous to 2.5, convert it information..
|
||||
data = {
|
||||
'ips': [v.split('=') for v in data.split(',')],
|
||||
'hostname': userService.friendly_name
|
||||
}
|
||||
|
||||
# We get from storage the name for this userService. If no name, we try to assign a new one
|
||||
ret = "ok"
|
||||
notifyReady = False
|
||||
@ -179,11 +187,6 @@ class WindowsOsManager(osmanagers.OSManager):
|
||||
doRemove = True
|
||||
elif msg == "ip":
|
||||
# This ocurss on main loop inside machine, so userService is usable
|
||||
if not isinstance(data, dict): # Old actors, previous to 2.5
|
||||
data = {
|
||||
'ips': [v.split('=') for v in data.split(',')],
|
||||
'hostname': userService.friendly_name
|
||||
}
|
||||
state = State.USABLE
|
||||
self.notifyIp(userService.unique_id, userService, data)
|
||||
elif msg == "ready":
|
||||
|
1
udsProxy/daemonize.txt
Normal file
1
udsProxy/daemonize.txt
Normal file
@ -0,0 +1 @@
|
||||
sudo daemonize -p /var/run/udsproxy.pid -l /var/lock/subsys/udsproxy -u nobody /home/dkmaster/projects/uds/openuds/udsProxy/bin/udsproxy
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -9,6 +10,8 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -19,21 +22,26 @@ import (
|
||||
const configFilename = "/etc/udsproxy.cfg"
|
||||
|
||||
var config struct {
|
||||
Server string // Server Type, "http" or "https"
|
||||
Port string // Server port
|
||||
SSLCertificateFile string // Certificate file
|
||||
SSLCertificateKeyFile string // Certificate key
|
||||
Broker string // Broker address
|
||||
UseSSL bool // If use https for connecting with broker: Warning, certificate must be valid on Broker
|
||||
Server string // Server Type, "http" or "https"
|
||||
Port string // Server port
|
||||
SSLCertificateFile string // Certificate file
|
||||
SSLCertificateKeyFile string // Certificate key
|
||||
Broker string // Broker address
|
||||
AllowFrom []string // Allow BROKER requests from this IPS
|
||||
UseSSL bool // If use https for connecting with broker: Warning, certificate must be valid on Broker
|
||||
IgnoreCertificates bool // If true, will ignore certificates (when requesting)
|
||||
}
|
||||
|
||||
func validOrigin(w http.ResponseWriter, r *http.Request) error {
|
||||
if strings.Split(r.RemoteAddr, ":")[0] != config.Broker {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
fmt.Fprintf(w, "Access denied")
|
||||
return errors.New("Invalid Origin")
|
||||
ip := strings.Split(r.RemoteAddr, ":")[0]
|
||||
for _, v := range config.AllowFrom {
|
||||
if v == ip {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
fmt.Fprintf(w, "Access denied")
|
||||
return errors.New("Invalid Origin")
|
||||
}
|
||||
|
||||
// Test service
|
||||
@ -43,8 +51,8 @@ func testService(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
r.ParseForm()
|
||||
ip, port, timeOutStr := r.FormValue("ip"), r.FormValue("port"), r.FormValue("timeout")
|
||||
if ip == "" || port == "" {
|
||||
host, port, timeOutStr := r.FormValue("host"), r.FormValue("port"), r.FormValue("timeout")
|
||||
if host == "" || port == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprintf(w, "Invalid arguments")
|
||||
return
|
||||
@ -55,8 +63,8 @@ func testService(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
timeOut, _ := strconv.Atoi(timeOutStr)
|
||||
|
||||
fmt.Println("Args: ", ip, port)
|
||||
con, err := net.DialTimeout("tcp", ip+":"+port, time.Duration(timeOut)*time.Second)
|
||||
fmt.Println("Args: ", host, port)
|
||||
con, err := net.DialTimeout("tcp", host+":"+port, time.Duration(timeOut)*time.Second)
|
||||
|
||||
if err == nil {
|
||||
con.Close()
|
||||
@ -86,7 +94,7 @@ func proxyRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if err := dec.Decode(&body); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprintf(w, "Error in Json: %s", err)
|
||||
log.Fatal(err)
|
||||
log.Printf("Error decoding json: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -104,24 +112,36 @@ func proxyRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprintf(w, "Error building request: %s", err)
|
||||
log.Printf("Error building request: %s", err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// Ignore Certificate
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: config.IgnoreCertificates},
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: time.Duration(5) * time.Second,
|
||||
Timeout: time.Duration(5) * time.Second,
|
||||
Transport: tr,
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
log.Printf("The connection failed %s", err)
|
||||
fmt.Fprintf(w, "Error in POST: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close() // Ensures closes response
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
log.Printf("Response: %d, %s", resp.StatusCode, b)
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
@ -145,7 +165,7 @@ func main() {
|
||||
|
||||
cfg, err := ini.Load(configFilename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatal(err) // Fatal calss exit
|
||||
}
|
||||
// Default config values
|
||||
config.Port = "9090"
|
||||
@ -153,13 +173,26 @@ func main() {
|
||||
// Read config
|
||||
cfg.MapTo(&config)
|
||||
|
||||
log.Printf("Broker address: %s", config.Broker)
|
||||
log.Printf("Broker: %s", config.Broker)
|
||||
log.Printf("Server type: %s", config.Server)
|
||||
log.Printf("Server port: %s", config.Port)
|
||||
log.Printf("Allow Access from: %s", config.AllowFrom)
|
||||
|
||||
// Handle signals
|
||||
// we make a buffered channel to do not loose signal
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, os.Kill)
|
||||
go func() {
|
||||
for range c {
|
||||
fmt.Print("Got Ending signal")
|
||||
os.Exit(0)
|
||||
}
|
||||
}()
|
||||
|
||||
http.HandleFunc("/actor", actor) // set router for "actor" requests
|
||||
http.HandleFunc("/testService", testService) // test service
|
||||
http.HandleFunc("/testServer", testService) // test service
|
||||
http.HandleFunc("/proxyRequest", proxyRequest) // Proxy request from broker to service
|
||||
|
||||
if config.Server == "https" {
|
||||
err = http.ListenAndServeTLS(":"+config.Port, config.SSLCertificateFile, config.SSLCertificateKeyFile, nil) // set listen port
|
||||
} else {
|
||||
@ -167,8 +200,7 @@ func main() {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
return
|
||||
log.Fatal("ListenAndServe: ", err) // Fatal calls exit
|
||||
}
|
||||
|
||||
}
|
9
udsProxy/udsproxy.cfg
Normal file
9
udsProxy/udsproxy.cfg
Normal file
@ -0,0 +1,9 @@
|
||||
Server = http
|
||||
Port = 9090
|
||||
SSLCertificateFile = /etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
SSLCertificateKeyFile = /etc/ssl/private/ssl-cert-snakeoil.key
|
||||
|
||||
IgnoreCertificates = True
|
||||
|
||||
Broker = https://172.27.0.1:8000
|
||||
AllowFrom = 172.27.0.1, 127.27.0.8
|
Loading…
x
Reference in New Issue
Block a user