diff --git a/rudder-server-relay/SOURCES/.dependencies b/rudder-server-relay/.dependencies
similarity index 100%
rename from rudder-server-relay/SOURCES/.dependencies
rename to rudder-server-relay/.dependencies
diff --git a/rudder-server-relay/SOURCES/Makefile b/rudder-server-relay/SOURCES/Makefile
deleted file mode 100644
index 2256bee17..000000000
--- a/rudder-server-relay/SOURCES/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-#####################################################################################
-# Copyright 2011 Normation SAS
-#####################################################################################
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, Version 3.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-#####################################################################################
-
-.DEFAULT_GOAL := localdepends
-
-RUDDER_VERSION_TO_PACKAGE =
-VIRTUALENV_RELEASE = 16.0.0
-VIRTUALENV_SHA256 = ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752
-
-# GENERIC_GET: do not remove this line
-# This is a generic get code that is common to many of our Makefiles.
-# The tag is here to find them. Rudder agent has an even more generic one.
-# If you change this code, change all the places where you can find this tag too.
-# It is duplicated because it is the code that is used to manage dependency
-# to other repositories, hence allowing deduplication of other code.
-# Autodetect wget, curl or fetch usage and proxy configuration
-# Usage: $(GET)
-PROXY_ENV = $(if $(PROXY), http_proxy=$(PROXY) ftp_proxy=$(PROXY))
-# No accept encoding to prevent the webserver form altering the distributed file
-WGET = wget -q --header="accept-encoding:" -O
-CURL = curl -s --http1.1 -L -o
-ifneq (,$(wildcard /usr/bin/curl))
-_GET = $(PROXY_ENV) $(CURL)
-else
-_GET = $(PROXY_ENV) $(WGET)
-endif
-# Pass an empty string to skip hash check
-GET=get() { $(_GET) "$$1.part" "$$2" && { openssl dgst -sha256 "$$1.part" | grep -q "$$3" || { echo "Wrong checksum, aborting"; exit 1; }; } && mv "$$1.part" "$$1"; }; get
-
-localdepends: ./rudder-sources ./relay-api/virtualenv/virtualenv.py
-
-./rudder-sources.tar.bz2:
- $(GET) rudder-sources.tar.bz2 https://www.rudder-project.org/archives/rudder-sources-${RUDDER_VERSION_TO_PACKAGE}.tar.bz2 ""
-
-./rudder-sources: ./rudder-sources.tar.bz2
- tar -xjf rudder-sources.tar.bz2
- mv rudder-sources-*/ rudder-sources/
-
-./relay-api/virtualenv.tgz: /usr/bin/wget
- # Original URL: https://pypi.python.org/packages/source/v/virtualenv/virtualenv-12.0.7.tar.gz
- $(GET) relay-api/virtualenv.tgz https://repository.rudder.io/build-dependencies/virtualenv/virtualenv-$(VIRTUALENV_RELEASE).tar.gz $(VIRTUALENV_SHA256)
-
-./relay-api/virtualenv/virtualenv.py: ./relay-api/virtualenv.tgz
- cd relay-api && tar -xzf ./virtualenv.tgz
- cd relay-api && mv ./virtualenv-$(VIRTUALENV_RELEASE)/ virtualenv/
-
-localclean:
- rm -rf ./rudder-sources
-
-veryclean:
- rm -f ./rudder-sources.tar.bz2
-
-.PHONY: localdepends localclean veryclean
diff --git a/rudder-server-relay/SOURCES/docopt.py b/rudder-server-relay/SOURCES/docopt.py
deleted file mode 100644
index 7b927e2f8..000000000
--- a/rudder-server-relay/SOURCES/docopt.py
+++ /dev/null
@@ -1,579 +0,0 @@
-"""Pythonic command-line interface parser that will make you smile.
-
- * http://docopt.org
- * Repository and issue-tracker: https://github.com/docopt/docopt
- * Licensed under terms of MIT license (see LICENSE-MIT)
- * Copyright (c) 2013 Vladimir Keleshev, vladimir@keleshev.com
-
-"""
-import sys
-import re
-
-
-__all__ = ['docopt']
-__version__ = '0.6.2'
-
-
-class DocoptLanguageError(Exception):
-
- """Error in construction of usage-message by developer."""
-
-
-class DocoptExit(SystemExit):
-
- """Exit in case user invoked program with incorrect arguments."""
-
- usage = ''
-
- def __init__(self, message=''):
- SystemExit.__init__(self, (message + '\n' + self.usage).strip())
-
-
-class Pattern(object):
-
- def __eq__(self, other):
- return repr(self) == repr(other)
-
- def __hash__(self):
- return hash(repr(self))
-
- def fix(self):
- self.fix_identities()
- self.fix_repeating_arguments()
- return self
-
- def fix_identities(self, uniq=None):
- """Make pattern-tree tips point to same object if they are equal."""
- if not hasattr(self, 'children'):
- return self
- uniq = list(set(self.flat())) if uniq is None else uniq
- for i, c in enumerate(self.children):
- if not hasattr(c, 'children'):
- assert c in uniq
- self.children[i] = uniq[uniq.index(c)]
- else:
- c.fix_identities(uniq)
-
- def fix_repeating_arguments(self):
- """Fix elements that should accumulate/increment values."""
- either = [list(c.children) for c in self.either.children]
- for case in either:
- for e in [c for c in case if case.count(c) > 1]:
- if type(e) is Argument or type(e) is Option and e.argcount:
- if e.value is None:
- e.value = []
- elif type(e.value) is not list:
- e.value = e.value.split()
- if type(e) is Command or type(e) is Option and e.argcount == 0:
- e.value = 0
- return self
-
- @property
- def either(self):
- """Transform pattern into an equivalent, with only top-level Either."""
- # Currently the pattern will not be equivalent, but more "narrow",
- # although good enough to reason about list arguments.
- ret = []
- groups = [[self]]
- while groups:
- children = groups.pop(0)
- types = [type(c) for c in children]
- if Either in types:
- either = [c for c in children if type(c) is Either][0]
- children.pop(children.index(either))
- for c in either.children:
- groups.append([c] + children)
- elif Required in types:
- required = [c for c in children if type(c) is Required][0]
- children.pop(children.index(required))
- groups.append(list(required.children) + children)
- elif Optional in types:
- optional = [c for c in children if type(c) is Optional][0]
- children.pop(children.index(optional))
- groups.append(list(optional.children) + children)
- elif AnyOptions in types:
- optional = [c for c in children if type(c) is AnyOptions][0]
- children.pop(children.index(optional))
- groups.append(list(optional.children) + children)
- elif OneOrMore in types:
- oneormore = [c for c in children if type(c) is OneOrMore][0]
- children.pop(children.index(oneormore))
- groups.append(list(oneormore.children) * 2 + children)
- else:
- ret.append(children)
- return Either(*[Required(*e) for e in ret])
-
-
-class ChildPattern(Pattern):
-
- def __init__(self, name, value=None):
- self.name = name
- self.value = value
-
- def __repr__(self):
- return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value)
-
- def flat(self, *types):
- return [self] if not types or type(self) in types else []
-
- def match(self, left, collected=None):
- collected = [] if collected is None else collected
- pos, match = self.single_match(left)
- if match is None:
- return False, left, collected
- left_ = left[:pos] + left[pos + 1:]
- same_name = [a for a in collected if a.name == self.name]
- if type(self.value) in (int, list):
- if type(self.value) is int:
- increment = 1
- else:
- increment = ([match.value] if type(match.value) is str
- else match.value)
- if not same_name:
- match.value = increment
- return True, left_, collected + [match]
- same_name[0].value += increment
- return True, left_, collected
- return True, left_, collected + [match]
-
-
-class ParentPattern(Pattern):
-
- def __init__(self, *children):
- self.children = list(children)
-
- def __repr__(self):
- return '%s(%s)' % (self.__class__.__name__,
- ', '.join(repr(a) for a in self.children))
-
- def flat(self, *types):
- if type(self) in types:
- return [self]
- return sum([c.flat(*types) for c in self.children], [])
-
-
-class Argument(ChildPattern):
-
- def single_match(self, left):
- for n, p in enumerate(left):
- if type(p) is Argument:
- return n, Argument(self.name, p.value)
- return None, None
-
- @classmethod
- def parse(class_, source):
- name = re.findall('(<\S*?>)', source)[0]
- value = re.findall('\[default: (.*)\]', source, flags=re.I)
- return class_(name, value[0] if value else None)
-
-
-class Command(Argument):
-
- def __init__(self, name, value=False):
- self.name = name
- self.value = value
-
- def single_match(self, left):
- for n, p in enumerate(left):
- if type(p) is Argument:
- if p.value == self.name:
- return n, Command(self.name, True)
- else:
- break
- return None, None
-
-
-class Option(ChildPattern):
-
- def __init__(self, short=None, long=None, argcount=0, value=False):
- assert argcount in (0, 1)
- self.short, self.long = short, long
- self.argcount, self.value = argcount, value
- self.value = None if value is False and argcount else value
-
- @classmethod
- def parse(class_, option_description):
- short, long, argcount, value = None, None, 0, False
- options, _, description = option_description.strip().partition(' ')
- options = options.replace(',', ' ').replace('=', ' ')
- for s in options.split():
- if s.startswith('--'):
- long = s
- elif s.startswith('-'):
- short = s
- else:
- argcount = 1
- if argcount:
- matched = re.findall('\[default: (.*)\]', description, flags=re.I)
- value = matched[0] if matched else None
- return class_(short, long, argcount, value)
-
- def single_match(self, left):
- for n, p in enumerate(left):
- if self.name == p.name:
- return n, p
- return None, None
-
- @property
- def name(self):
- return self.long or self.short
-
- def __repr__(self):
- return 'Option(%r, %r, %r, %r)' % (self.short, self.long,
- self.argcount, self.value)
-
-
-class Required(ParentPattern):
-
- def match(self, left, collected=None):
- collected = [] if collected is None else collected
- l = left
- c = collected
- for p in self.children:
- matched, l, c = p.match(l, c)
- if not matched:
- return False, left, collected
- return True, l, c
-
-
-class Optional(ParentPattern):
-
- def match(self, left, collected=None):
- collected = [] if collected is None else collected
- for p in self.children:
- m, left, collected = p.match(left, collected)
- return True, left, collected
-
-
-class AnyOptions(Optional):
-
- """Marker/placeholder for [options] shortcut."""
-
-
-class OneOrMore(ParentPattern):
-
- def match(self, left, collected=None):
- assert len(self.children) == 1
- collected = [] if collected is None else collected
- l = left
- c = collected
- l_ = None
- matched = True
- times = 0
- while matched:
- # could it be that something didn't match but changed l or c?
- matched, l, c = self.children[0].match(l, c)
- times += 1 if matched else 0
- if l_ == l:
- break
- l_ = l
- if times >= 1:
- return True, l, c
- return False, left, collected
-
-
-class Either(ParentPattern):
-
- def match(self, left, collected=None):
- collected = [] if collected is None else collected
- outcomes = []
- for p in self.children:
- matched, _, _ = outcome = p.match(left, collected)
- if matched:
- outcomes.append(outcome)
- if outcomes:
- return min(outcomes, key=lambda outcome: len(outcome[1]))
- return False, left, collected
-
-
-class TokenStream(list):
-
- def __init__(self, source, error):
- self += source.split() if hasattr(source, 'split') else source
- self.error = error
-
- def move(self):
- return self.pop(0) if len(self) else None
-
- def current(self):
- return self[0] if len(self) else None
-
-
-def parse_long(tokens, options):
- """long ::= '--' chars [ ( ' ' | '=' ) chars ] ;"""
- long, eq, value = tokens.move().partition('=')
- assert long.startswith('--')
- value = None if eq == value == '' else value
- similar = [o for o in options if o.long == long]
- if tokens.error is DocoptExit and similar == []: # if no exact match
- similar = [o for o in options if o.long and o.long.startswith(long)]
- if len(similar) > 1: # might be simply specified ambiguously 2+ times?
- raise tokens.error('%s is not a unique prefix: %s?' %
- (long, ', '.join(o.long for o in similar)))
- elif len(similar) < 1:
- argcount = 1 if eq == '=' else 0
- o = Option(None, long, argcount)
- options.append(o)
- if tokens.error is DocoptExit:
- o = Option(None, long, argcount, value if argcount else True)
- else:
- o = Option(similar[0].short, similar[0].long,
- similar[0].argcount, similar[0].value)
- if o.argcount == 0:
- if value is not None:
- raise tokens.error('%s must not have an argument' % o.long)
- else:
- if value is None:
- if tokens.current() is None:
- raise tokens.error('%s requires argument' % o.long)
- value = tokens.move()
- if tokens.error is DocoptExit:
- o.value = value if value is not None else True
- return [o]
-
-
-def parse_shorts(tokens, options):
- """shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;"""
- token = tokens.move()
- assert token.startswith('-') and not token.startswith('--')
- left = token.lstrip('-')
- parsed = []
- while left != '':
- short, left = '-' + left[0], left[1:]
- similar = [o for o in options if o.short == short]
- if len(similar) > 1:
- raise tokens.error('%s is specified ambiguously %d times' %
- (short, len(similar)))
- elif len(similar) < 1:
- o = Option(short, None, 0)
- options.append(o)
- if tokens.error is DocoptExit:
- o = Option(short, None, 0, True)
- else: # why copying is necessary here?
- o = Option(short, similar[0].long,
- similar[0].argcount, similar[0].value)
- value = None
- if o.argcount != 0:
- if left == '':
- if tokens.current() is None:
- raise tokens.error('%s requires argument' % short)
- value = tokens.move()
- else:
- value = left
- left = ''
- if tokens.error is DocoptExit:
- o.value = value if value is not None else True
- parsed.append(o)
- return parsed
-
-
-def parse_pattern(source, options):
- tokens = TokenStream(re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source),
- DocoptLanguageError)
- result = parse_expr(tokens, options)
- if tokens.current() is not None:
- raise tokens.error('unexpected ending: %r' % ' '.join(tokens))
- return Required(*result)
-
-
-def parse_expr(tokens, options):
- """expr ::= seq ( '|' seq )* ;"""
- seq = parse_seq(tokens, options)
- if tokens.current() != '|':
- return seq
- result = [Required(*seq)] if len(seq) > 1 else seq
- while tokens.current() == '|':
- tokens.move()
- seq = parse_seq(tokens, options)
- result += [Required(*seq)] if len(seq) > 1 else seq
- return [Either(*result)] if len(result) > 1 else result
-
-
-def parse_seq(tokens, options):
- """seq ::= ( atom [ '...' ] )* ;"""
- result = []
- while tokens.current() not in [None, ']', ')', '|']:
- atom = parse_atom(tokens, options)
- if tokens.current() == '...':
- atom = [OneOrMore(*atom)]
- tokens.move()
- result += atom
- return result
-
-
-def parse_atom(tokens, options):
- """atom ::= '(' expr ')' | '[' expr ']' | 'options'
- | long | shorts | argument | command ;
- """
- token = tokens.current()
- result = []
- if token in '([':
- tokens.move()
- matching, pattern = {'(': [')', Required], '[': [']', Optional]}[token]
- result = pattern(*parse_expr(tokens, options))
- if tokens.move() != matching:
- raise tokens.error("unmatched '%s'" % token)
- return [result]
- elif token == 'options':
- tokens.move()
- return [AnyOptions()]
- elif token.startswith('--') and token != '--':
- return parse_long(tokens, options)
- elif token.startswith('-') and token not in ('-', '--'):
- return parse_shorts(tokens, options)
- elif token.startswith('<') and token.endswith('>') or token.isupper():
- return [Argument(tokens.move())]
- else:
- return [Command(tokens.move())]
-
-
-def parse_argv(tokens, options, options_first=False):
- """Parse command-line argument vector.
-
- If options_first:
- argv ::= [ long | shorts ]* [ argument ]* [ '--' [ argument ]* ] ;
- else:
- argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ;
-
- """
- parsed = []
- while tokens.current() is not None:
- if tokens.current() == '--':
- return parsed + [Argument(None, v) for v in tokens]
- elif tokens.current().startswith('--'):
- parsed += parse_long(tokens, options)
- elif tokens.current().startswith('-') and tokens.current() != '-':
- parsed += parse_shorts(tokens, options)
- elif options_first:
- return parsed + [Argument(None, v) for v in tokens]
- else:
- parsed.append(Argument(None, tokens.move()))
- return parsed
-
-
-def parse_defaults(doc):
- # in python < 2.7 you can't pass flags=re.MULTILINE
- split = re.split('\n *(<\S+?>|-\S+?)', doc)[1:]
- split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
- options = [Option.parse(s) for s in split if s.startswith('-')]
- #arguments = [Argument.parse(s) for s in split if s.startswith('<')]
- #return options, arguments
- return options
-
-
-def printable_usage(doc):
- # in python < 2.7 you can't pass flags=re.IGNORECASE
- usage_split = re.split(r'([Uu][Ss][Aa][Gg][Ee]:)', doc)
- if len(usage_split) < 3:
- raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
- if len(usage_split) > 3:
- raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
- return re.split(r'\n\s*\n', ''.join(usage_split[1:]))[0].strip()
-
-
-def formal_usage(printable_usage):
- pu = printable_usage.split()[1:] # split and drop "usage:"
- return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )'
-
-
-def extras(help, version, options, doc):
- if help and any((o.name in ('-h', '--help')) and o.value for o in options):
- print(doc.strip("\n"))
- sys.exit()
- if version and any(o.name == '--version' and o.value for o in options):
- print(version)
- sys.exit()
-
-
-class Dict(dict):
- def __repr__(self):
- return '{%s}' % ',\n '.join('%r: %r' % i for i in sorted(self.items()))
-
-
-def docopt(doc, argv=None, help=True, version=None, options_first=False):
- """Parse `argv` based on command-line interface described in `doc`.
-
- `docopt` creates your command-line interface based on its
- description that you pass as `doc`. Such description can contain
- --options, , commands, which could be
- [optional], (required), (mutually | exclusive) or repeated...
-
- Parameters
- ----------
- doc : str
- Description of your command-line interface.
- argv : list of str, optional
- Argument vector to be parsed. sys.argv[1:] is used if not
- provided.
- help : bool (default: True)
- Set to False to disable automatic help on -h or --help
- options.
- version : any object
- If passed, the object will be printed if --version is in
- `argv`.
- options_first : bool (default: False)
- Set to True to require options preceed positional arguments,
- i.e. to forbid options and positional arguments intermix.
-
- Returns
- -------
- args : dict
- A dictionary, where keys are names of command-line elements
- such as e.g. "--verbose" and "", and values are the
- parsed values of those elements.
-
- Example
- -------
- >>> from docopt import docopt
- >>> doc = '''
- Usage:
- my_program tcp [--timeout=]
- my_program serial [--baud=] [--timeout=]
- my_program (-h | --help | --version)
-
- Options:
- -h, --help Show this screen and exit.
- --baud= Baudrate [default: 9600]
- '''
- >>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30']
- >>> docopt(doc, argv)
- {'--baud': '9600',
- '--help': False,
- '--timeout': '30',
- '--version': False,
- '': '127.0.0.1',
- '': '80',
- 'serial': False,
- 'tcp': True}
-
- See also
- --------
- * For video introduction see http://docopt.org
- * Full documentation is available in README.rst as well as online
- at https://github.com/docopt/docopt#readme
-
- """
- if argv is None:
- argv = sys.argv[1:]
- DocoptExit.usage = printable_usage(doc)
- options = parse_defaults(doc)
- pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
- # [default] syntax for argument is disabled
- #for a in pattern.flat(Argument):
- # same_name = [d for d in arguments if d.name == a.name]
- # if same_name:
- # a.value = same_name[0].value
- argv = parse_argv(TokenStream(argv, DocoptExit), list(options),
- options_first)
- pattern_options = set(pattern.flat(Option))
- for ao in pattern.flat(AnyOptions):
- doc_options = parse_defaults(doc)
- ao.children = list(set(doc_options) - pattern_options)
- #if any_options:
- # ao.children += [Option(o.short, o.long, o.argcount)
- # for o in argv if type(o) is Option]
- extras(help, version, argv, doc)
- matched, left, collected = pattern.fix().match(argv)
- if matched and left == []: # better error message if left?
- return Dict((a.name, a.value) for a in (pattern.flat() + collected))
- raise DocoptExit()
diff --git a/rudder-server-relay/SOURCES/openssl.cnf b/rudder-server-relay/SOURCES/openssl.cnf
deleted file mode 100644
index 8bc9ca849..000000000
--- a/rudder-server-relay/SOURCES/openssl.cnf
+++ /dev/null
@@ -1,28 +0,0 @@
-[ req ]
-distinguished_name = req_distinguished_name
-
-[ req_distinguished_name ]
-
-[ server_cert ]
-
-# Self signed cert must be a CA to authenticate
-basicConstraints = CA:TRUE
-
-# Client authentication and signature (deprecated)
-#nsCertType = client, objsign
-
-# digitalSignature: to sign files (e.g. inventories)
-# keyEncipherment: to cipher session keys (e.g. TLS session)
-# dataEncipherment: to cipher files, mays be used some day
-# keyCertSign: to sign certificate (as a CA or for self signed certs)
-keyUsage = digitalSignature, keyEncipherment, dataEncipherment, keyCertSign
-
-# Optional, no generic signature usage, do not use
-# clientAuth: for TLS communication
-#extendedKeyUsage = clientAuth
-
-# PKIX recommendations
-subjectKeyIdentifier=hash
-
-subjectAltName = $ENV::SUBJALTNAME
-
diff --git a/rudder-server-relay/SOURCES/relay-api/.gitignore b/rudder-server-relay/SOURCES/relay-api/.gitignore
deleted file mode 100644
index a44542ded..000000000
--- a/rudder-server-relay/SOURCES/relay-api/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-flask
-*.pyc
diff --git a/rudder-server-relay/SOURCES/relay-api/README b/rudder-server-relay/SOURCES/relay-api/README
deleted file mode 100644
index 29f2866cf..000000000
--- a/rudder-server-relay/SOURCES/relay-api/README
+++ /dev/null
@@ -1,41 +0,0 @@
-How to setup the API
---------------------
-
-Initialize the virtualenv with
-$ ./virtualenv.py flask
-
-Activate the virtualenv
-$ . flask/bin/activate
-
-Install dependencies
-$ pip install -r requirements.txt
-
-Modify and include apache/relay-api.conf in your apache configuration
-
-How to test the shared-files API
---------------------------------
-
-Have a nodeslist.json in /var/rudder/cfengine-community/inputs/distributePolicy/1.0/nodeslist.json
-Have a policy_server in /var/rudder/cfengine-community/policy_server.dat
-Have a uuid file in /opt/rudder/etc/uuid.hive
-Hase a key pair in /var/rudder/cfengine-community/ppkeys/localhost.{priv,pub}
-
-Launch a local API server
-$ ./run.py
-
-Create a signature (you need a cfengine key)
-$ /opt/rudder/bin/rudder-sign file
-
-Add the public key and TTL
-$ echo pubkey=$(cat /var/rudder/cfengine-community/ppkeys/localhost.pub | grep -v -- -- | perl -pe 's/\n//g'i) >> file.sign
-$ echo "ttl=1m" >> file.sign
-
-Create the data to send
-$ echo "" | cat file.sign - file > putdata
-
-Send the data file
-$ curl -T putdata http://127.0.0.1:5000/shared-files/target_uuid/source_uuid/filename
-
-Test a file presence
-$ curl -w "%{http_code}\n" -X HEAD http://127.0.0.1:5000/shared-files/target_uuid/source_uuid/filename?hash=....
-
diff --git a/rudder-server-relay/SOURCES/relay-api/apache/relay-api.wsgi b/rudder-server-relay/SOURCES/relay-api/apache/relay-api.wsgi
deleted file mode 100644
index 28bb7b372..000000000
--- a/rudder-server-relay/SOURCES/relay-api/apache/relay-api.wsgi
+++ /dev/null
@@ -1,16 +0,0 @@
-# Import core modules
-import sys
-
-# Set up paths
-api_path = '/opt/rudder/share/relay-api'
-virtualenv_path = '/opt/rudder/share/relay-api/flask'
-
-# Virtualenv initialization
-activate_this = virtualenv_path + '/bin/activate_this.py'
-execfile(activate_this, dict(__file__=activate_this))
-
-# Append ncf API path to the current one
-sys.path.append(api_path)
-
-# Launch
-from relay_api import app as application
diff --git a/rudder-server-relay/SOURCES/relay-api/cleanup.sh b/rudder-server-relay/SOURCES/relay-api/cleanup.sh
deleted file mode 100755
index 8253e31f9..000000000
--- a/rudder-server-relay/SOURCES/relay-api/cleanup.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-# remove all files and their metadata in BASEDIR that have expired
-
-BASEDIR="/var/rudder/shared-files"
-date=$(date +%s)
-find "${BASEDIR}" -type f -name '*.metadata' | xargs grep -H 'expires=' | sed 's/^\(.*\).metadata:expires=/\1 /' |
-while read f d
-do
- if [ ${date} -gt ${d} ]
- then
- rm "${f}" "${f}.metadata"
- fi
-done
diff --git a/rudder-server-relay/SOURCES/relay-api/nodeslist.json.example b/rudder-server-relay/SOURCES/relay-api/nodeslist.json.example
deleted file mode 100644
index 6a3283854..000000000
--- a/rudder-server-relay/SOURCES/relay-api/nodeslist.json.example
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "c5e38f75-3fbe-402f-ac78-4ada2ea784a5": {
- "hostname": "host1.rudder.local",
- "key-hash": "sha1:da39a3ee5e6b4b0d3255bfef95601890afd80709",
- "policy-server": "9b25d384-a0ed-4ac1-adf2-b5b0277a455d"
- },
- "6b26bf62-fe19-45ba-a0bc-4a1ddeca52ef": {
- "hostname": "host2.rudder.local",
- "key-hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- "policy-server": "9b25d384-a0ed-4ac1-adf2-b5b0277a455d"
- },
- "465b0ed4-6cad-4dc3-a0ec-cf84c8e1d752": {
- "hostname": "host3.rudder.local",
- "key-hash": "sha512:cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
- "policy-server": "6b26bf62-fe19-45ba-a0bc-4a1ddeca52ef"
- },
- "bf745c11-e995-4b4c-806a-86604708cfc3": {
- "hostname": "host4.rudder.local",
- "key-hash": "sha1:0539a3ee5e6b4b0d3255bfef95601890afd80710",
- "policy-server": "465b0ed4-6cad-4dc3-a0ec-cf84c8e1d752"
- }
-}
diff --git a/rudder-server-relay/SOURCES/relay-api/relay_api/__init__.py b/rudder-server-relay/SOURCES/relay-api/relay_api/__init__.py
deleted file mode 100755
index b097c9768..000000000
--- a/rudder-server-relay/SOURCES/relay-api/relay_api/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from flask import Flask
-
-app = Flask(__name__)
-
-from relay_api import views
diff --git a/rudder-server-relay/SOURCES/relay-api/relay_api/common.py b/rudder-server-relay/SOURCES/relay-api/relay_api/common.py
deleted file mode 100644
index cb46ed033..000000000
--- a/rudder-server-relay/SOURCES/relay-api/relay_api/common.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import traceback
-import json
-from flask import Flask, jsonify, request, abort, make_response
-
-NODES=None
-
-
-# Format error as api output
-def format_error(exception, debug):
- message = "Internal error!\n"
- message += "Cause: " + type(u'')(exception) + "\n"
- if debug:
- message += traceback.format_exc() + "\n"
- error = make_response(message)
- error.headers['Content-Type'] = 'text/plain; charset=utf-8'
- error.status_code = 500
- return error
-
-
-# Format a success response as api output
-def format_response(text, code=200):
- response = make_response(text)
- response.headers['Content-Type'] = 'text/plain; charset=utf-8'
- response.status_code = code
- return response
-
-
-# returns the UUID of localhost
-def get_file_content(filename):
- fd = open(filename, 'r')
- content = fd.read().replace('\n','').strip()
- fd.close()
- return content
-
-
-# returns [ relay_uuid, ... , node_uuid ], not including self
-def node_route(nodes, my_uuid, uuid):
- if uuid not in nodes:
- raise ValueError("ERROR unknown node: " + str(uuid))
- if "policy-server" not in nodes[uuid]:
- raise ValueError("ERROR invalid nodes file on the server for " + uuid)
- server = nodes[uuid]["policy-server"]
- if server == my_uuid:
- return [uuid]
- route = node_route(nodes, my_uuid, server)
- route.append(uuid)
- return route
-
-
-# Returns the parsed content of the nodeslist file
-def get_nodes_list(nodeslist_file):
- global NODES
- ## uncomment to enable nodeslist caching
- #if NODES is not None:
- # return NODES
- fd = open(nodeslist_file, 'r')
- NODES = json.load(fd)
- fd.close()
- return NODES
-
diff --git a/rudder-server-relay/SOURCES/relay-api/relay_api/remote_run.py b/rudder-server-relay/SOURCES/relay-api/relay_api/remote_run.py
deleted file mode 100644
index 3fe768cb5..000000000
--- a/rudder-server-relay/SOURCES/relay-api/relay_api/remote_run.py
+++ /dev/null
@@ -1,201 +0,0 @@
-from relay_api.common import *
-
-import base64
-import re
-import os
-import datetime
-import requests
-from subprocess import Popen, PIPE, STDOUT
-from flask import Flask, Response
-import itertools
-
-# disable ssl warning on rudder connection in all the possible ways
-try:
- import urllib3
- urllib3.disable_warnings()
-except:
- pass
-
-try:
- requests.packages.urllib3.disable_warnings()
-except:
- pass
-
-NEXTHOP = None
-REMOTE_RUN_COMMAND = "sudo /opt/rudder/bin/rudder remote run"
-LOCAL_RUN_COMMAND = "sudo /opt/rudder/bin/rudder agent run > /dev/null 2>&1"
-
-def get_next_hop(nodes, my_uuid):
- """ Build a dict of node_id => nexthop_id """
- global NEXTHOP
- ## uncomment to enable nexthop caching caching (depends on nodeslist caching)
- #if NEXTHOP is not None:
- # return NEXTHOP
- #else:
- NEXTHOP = {}
- for node in nodes:
- NEXTHOP[node] = node_route(nodes, my_uuid, node)[0]
- return NEXTHOP
-
-def get_all_my_nodes(nexthop):
- """ Get all my directly connected nodes """
- result = []
- for node in nexthop:
- if nexthop[node] == node:
- result.append(node)
- return result
-
-def get_my_nodes(nexthop, nodes):
- """ Get all nodes directly connected in the given list """
- result = []
- for node in nodes:
- if node not in nexthop:
- raise ValueError("ERROR unknown node: " + str(node))
- if nexthop[node] == node:
- result.append(node)
- return result
-
-def get_relay_nodes(nexthop, relay, nodes):
- """ Get all nodes behind the given relay from the given list """
- result = []
- for node in nodes:
- if node not in nexthop:
- raise ValueError("ERROR unknown node: " + str(node))
- if nexthop[node] == relay and nexthop[node] != node:
- result.append(node)
- return result
-
-def get_next_relays(nexthop):
- """ Get a list of all relays directly connected to me """
- result = set([])
- for node in nexthop:
- next_hop = nexthop[node]
- if next_hop != node:
- result.add(next_hop)
- return result
-
-def resolve_hostname(local_nodes, node):
- """ Get the hostname of a node from its uuid """
- if node not in local_nodes:
- raise ValueError("ERROR unknown node: " + str(node))
- if "hostname" not in local_nodes[node]:
- raise ValueError("ERROR invalid nodes file on the server for " + node)
- return local_nodes[node]["hostname"]
-
-def call_agent_run(host, uuid, classes, keep_output, asynchronous):
- """ Call the run command locally """
- if classes:
- classes_parameter = " -D " + classes
- else:
- classes_parameter = ""
-
- if uuid == "root":
- # root cannot make a remote run call to itself (certificate is not recognized correctly)
- # We do a standard local run instead.
- command = LOCAL_RUN_COMMAND
- else:
- command = REMOTE_RUN_COMMAND
- return run_command(command + classes_parameter + " " + host, uuid, keep_output, asynchronous)
-
-def run_command(command, prefix, keep_output, asynchronous):
- """ Run the given command, prefixing all output lines with prefix """
-
- if keep_output:
- process = Popen(command, shell=True, stdout=PIPE, stderr=STDOUT)
- if not asynchronous:
- output = "".join([prefix + ":" + line for line in process.stdout.readlines()])
- process.wait()
- else:
- def stream():
- for line in iter(process.stdout.readline,''):
- yield prefix + ":" + line.rstrip()+"\n"
- output=stream()
- else:
- output = ""
- process = Popen(command, shell=True)
- if not asynchronous:
- process.wait()
- return output
-
-def make_api_call(host, nodes, all_nodes, classes, keep_output, asynchronous):
- if all_nodes:
- method = "all"
- else:
- method = "nodes"
-
- url = "https://" + host + "/rudder/relay-api/remote-run/" + method
-
- data = {}
-
- if classes:
- data["classes"] = classes
-
- data["keep_output"] = keep_output
- data["asynchronous"] = asynchronous
-
- if nodes:
- data["nodes"] = ",".join(nodes)
-
- req = requests.post(url, data=data, verify=False, stream = asynchronous)
- if req.status_code == 200:
- response = ""
- if asynchronous:
- def stream():
- for content in req.iter_lines():
- yield content+"\n"
- response = stream()
- else:
- response = req.text
- return response
- else:
- raise ValueError("Upstream Error: " + req.text)
-
-def remote_run_generic(local_nodes, my_uuid, nodes, all_nodes, form):
- # Set default option values
- classes = None
- keep_output = False
- asynchronous = False
-
- if "classes" in form:
- classes = form['classes']
-
- if "keep_output" in form:
- keep_output = form['keep_output'].lower() == "true"
-
- if "asynchronous" in form:
- asynchronous = form['asynchronous'].lower() == "true"
-
- NEXTHOP = get_next_hop(local_nodes, my_uuid)
-
- def generate_output():
- result = []
- # Pass the call to sub relays
- for relay in get_next_relays(NEXTHOP):
- host = resolve_hostname(local_nodes, relay)
- if all_nodes:
- result.append(make_api_call(host, None, all_nodes, classes, keep_output, asynchronous))
- else:
- relay_nodes = get_relay_nodes(NEXTHOP, relay, nodes)
- if relay_nodes:
- result.append(make_api_call(host, get_relay_nodes(NEXTHOP, relay, nodes), all_nodes, classes, keep_output, asynchronous))
- # Call directly managed nodes when needed
- if all_nodes:
- local_nodes_to_call = get_all_my_nodes(NEXTHOP)
- else:
- local_nodes_to_call = get_my_nodes(NEXTHOP, nodes)
- for node in local_nodes_to_call:
- host = resolve_hostname(local_nodes, node)
- result.append( call_agent_run(host, node, classes, keep_output, asynchronous))
- return result
-
- # depending on wether we want an asynch result we need to do something different on the output
- if asynchronous:
- # An async response, we produce generators that will be the result of our various async calls
- # We jsut need to chain them
- # May be could mix them ? Don't know how ( pipe ? outputstream ? )
- response = itertools.chain(* generate_output())
- else:
- # A synch response, we already have the final output and
- response = "\n".join(generate_output())
-
- return Response(response )
diff --git a/rudder-server-relay/SOURCES/relay-api/relay_api/shared_files.py b/rudder-server-relay/SOURCES/relay-api/relay_api/shared_files.py
deleted file mode 100644
index 361a9628b..000000000
--- a/rudder-server-relay/SOURCES/relay-api/relay_api/shared_files.py
+++ /dev/null
@@ -1,334 +0,0 @@
-from relay_api.common import *
-
-import base64
-import re
-import os
-import datetime
-import requests
-import hashlib
-
-# disable ssl warning on rudder connection in all the possible ways
-try:
- import urllib3
- urllib3.disable_warnings()
-except:
- pass
-
-try:
- from requests.packages import urllib3
- urllib3.disable_warnings()
-except:
- pass
-
-from pprint import pprint
-from Crypto.Hash import SHA, SHA256, SHA512
-from Crypto.Signature import PKCS1_v1_5
-from Crypto.PublicKey import RSA
-
-
-SIGNATURE_FORMAT="header=rudder-signature-v1"
-METADATA_EXTENSION=".metadata"
-BLOCKSIZE = 65536
-SHARED_FOLDER="/var/rudder/configuration-repository/shared-files"
-
-# convert a byte string to hexadecimal representation
-toHex = lambda x:"".join([hex(ord(c))[2:].zfill(2) for c in x])
-
-# convert an hexadecimal string to a byte string
-toBin = lambda x:"".join([chr(int(x[c:c+2],16)) for c in range(0,len(x),2)])
-
-# Parse a ttl string of the form "1day 2hours 3minute 4seconds"
-# It can be abreviated to thos form "5h 3s"
-# If it is a pure integer it is considered to be seconds
-# Returns a timedelta object
-def parse_ttl(string):
- m = re.match(r'^\s*(\d+)\s*$', string)
- if m:
- days = 0
- seconds = int(m.group(1))
- else:
- daymatch = r'(\d+)\s*d(?:ays?)?'
- hourmatch = r'(\d+)\s*h(?:ours?)?'
- minmatch = r'(\d+)\s*m(?:inutes?)?'
- secmatch = r'(\d+)\s*s(?:econds?)?'
- match = r'^\s*(?:' + daymatch + r')?\s*(?:' + hourmatch + r')?\s*(?:' + minmatch + r')?\s*(?:' + secmatch + r')?\s*$'
- m = re.match(match, string)
- if m:
- days = 0
- seconds = 0
- if m.group(1) is not None:
- days = int(m.group(1))
- if m.group(2) is not None:
- seconds += 3600 * int(m.group(2))
- if m.group(3) is not None:
- seconds += 60 * int(m.group(3))
- if m.group(4) is not None:
- seconds += int(m.group(4))
- else:
- raise ValueError("ERROR invalid TTL specification:" + string)
- return datetime.timedelta(days, seconds)
-
-
-# Extract the signature header from a data stream
-# The header is delimited by an empty line
-def get_header(data_stream):
- # format parsing
- line = data_stream.readline()
- if line.rstrip() != SIGNATURE_FORMAT:
- raise ValueError("ERROR unknown signature format: " + str(line))
- header = line
- while True:
- line = data_stream.readline()
- if line == "\n":
- return header
- header += line
- # the return is just above
-
-
-# Extract informations from header
-def parse_header(header):
- data = {}
- for line in header.rstrip().split("\n"):
- m = re.match(r"(\w+)\s*=\s*(.*)", line)
- if m:
- data[m.group(1)] = m.group(2)
- else:
- raise ValueError("ERROR invalid format: " + line)
- return data
-
-
-# Extract a public key object from headers
-def get_pubkey(header_info):
- # validate header content first
- if 'digest' not in header_info or 'short_pubkey' not in header_info:
- raise ValueError("ERROR incomplete header, missing digest or public key")
- pem = "-----BEGIN RSA PRIVATE KEY-----\n" + header_info['short_pubkey'] + "\n-----END RSA PRIVATE KEY-----\n"
- return RSA.importKey(pem)
-
-
-# Create expiry header line
-def expiry_line(header_info, ttl_value):
- if ttl_value is None or ttl_value == '':
- if 'ttl' not in header_info:
- raise ValueError("ERROR: No TTL provided")
- ttl = parse_ttl(header_info['ttl'])
- else:
- ttl = parse_ttl(ttl_value)
- expires = datetime.datetime.utcnow() + ttl # we take utcnow because we write a unix timestamp
- delta = expires - datetime.datetime(1970, 1, 1)
- timestamp = delta.days*24*3600 + delta.seconds # convert to unix timestamp
- return "expires=" + str(timestamp) + "\n"
-
-
-# Hash a message with a given algorithm
-# Returns a hash object
-def get_hash(algorithm, message):
- if algorithm == "sha1":
- h=SHA.new(message)
- elif algorithm == "sha256":
- h=SHA256.new(message)
- elif algorithm == "sha512":
- h=SHA512.new(message)
- else:
- raise ValueError("ERROR unknown key hash type: " + str(algorithm))
- return h
-
-
-# Validate that a given public key matches the provided hash
-# The public key is a key object and the hash is of the form 'algorithm:kex_value'
-def validate_key(pubkey, keyhash):
- try:
- (keyhash_type, keyhash_value) = keyhash.split(":",1)
- except:
- raise ValueError("ERROR invalid key hash, it should be 'type:value': " + keyhash)
- pubkey_bin = pubkey.exportKey(format="DER")
- h = get_hash(keyhash_type, pubkey_bin)
- return h.hexdigest() == keyhash_value
-
-# Validate that a message has been properly signed by the given key
-# The public key is a key object, algorithm is the hash algorithm and digest the hex signature
-# The key algorithm will always be RSA because is is loaded as such
-# Returns a booleas for the validity and the message hash to avoid computing it twice
-def validate_message(message, pubkey, algorithm, digest):
- h = get_hash(algorithm, message)
- cipher = PKCS1_v1_5.new(pubkey)
- return (cipher.verify(h, toBin(digest)), h.hexdigest())
-
-
-# Find in which directory a shared file should be stored
-def file_directory(shared_path, nodes, my_uuid, target_uuid, source_uuid, file_id):
- if not re.match(r"^[\w\-.]+$", file_id):
- raise ValueError("ERROR file_id must be an identifier [A-z0-9_-.]: " + str(file_id))
- route_path = '/shared-files/'.join(node_route(nodes, my_uuid, target_uuid))
- return shared_path + "/" + route_path + "/files/" + source_uuid
-
-
-# Returns the stored hash from the metadata file
-def get_metadata_hash(metadata_file):
- fd = open(metadata_file, 'r')
- line = fd.readline().rstrip()
- if line != SIGNATURE_FORMAT:
- fd.close()
- raise ValueError("ERROR invalid storage: " + line)
- while True:
- line = fd.readline().rstrip()
- m = re.match(r"(\w+)\s*=\s*(.*)", line)
- if m:
- if m.group(1) == "hash_value":
- fd.close()
- return m.group(2)
- else:
- fd.close()
- raise ValueError("ERROR invalid storage: " + line)
-
-def get_shared_folder_hash(file_path, hasher):
- with open(file_path, 'rb') as afile:
- buf = afile.read(BLOCKSIZE)
- while len(buf) > 0:
- hasher.update(buf)
- buf = afile.read(BLOCKSIZE)
- return hasher.hexdigest()
-
-# =====================
-# Manage PUT API call
-# =====================
-# Parameters:
-# - target_uuid where to send the file to
-# - source_uuid who sent the file
-# - file_id under which name to store the file
-# - data the file content
-# - nodes the content of the nodes_list file
-# - my_uuid uuid of the current relay (self)
-# - shared_path the shared-files directory path
-# - ttl duration to keep the file
-# Returns the full path of the created file
-def shared_files_put(target_uuid, source_uuid, file_id, data_stream, nodes, my_uuid, shared_path, ttl):
- header = get_header(data_stream)
- info = parse_header(header)
-
- # extract information
- pubkey = get_pubkey(info)
- if source_uuid not in nodes:
- raise ValueError("ERROR unknown source node: " + str(source_uuid))
- if "key-hash" not in nodes[source_uuid]:
- raise ValueError("ERROR invalid nodes file on the server for " + source_uuid)
- keyhash = nodes[source_uuid]["key-hash"]
-
- # validate key
- if not validate_key(pubkey, keyhash):
- raise ValueError("ERROR invalid public key or not matching UUID")
-
- # validate message
- message = data_stream.read()
- (validated, message_hash) = validate_message(message, pubkey, info['algorithm'], info['digest'])
- if not validated:
- raise ValueError("ERROR invalid signature")
-
- # add headers
- header += expiry_line(info, ttl)
- # replace hash by a guaranteed one
- header = re.sub(r'hash_value=.*?\n', "hash_value=" + message_hash + "\n", header)
-
- # where to store file
- path = file_directory(shared_path, nodes, my_uuid, target_uuid, source_uuid, file_id)
- filename = path + "/" + file_id
-
- # write data & metadata
- try:
- os.makedirs(path, 0o750)
- except:
- pass # makedirs fails if the directory exists
- fd = open(filename, 'w')
- fd.write(message)
- fd.close()
- fd = open(filename + METADATA_EXTENSION, 'w')
- fd.write(header)
- fd.close()
- return filename
-
-
-# ======================
-# Forward PUT API call
-# ======================
-# Parameters:
-# - stream stream of posted data
-# - url where to forward to
-# Returns the full path of the created file
-def shared_files_put_forward(stream, url):
- # This is needed to make requests know the length
- # It will avoid streaming the content which would make the next hop fail
- stream.len = stream.limit
- req = requests.put(url, data=stream, verify=False)
- if req.status_code == 200:
- return req.text
- else:
- raise ValueError("Upstream Error: " + req.text)
-
-# ======================
-# Manage HEAD API call
-# ======================
-# Parameters:
-# - target_uuid where to send the file to
-# - source_uuid who sent the file
-# - file_id under which name to store the file
-# - file_hash the hash to compare with
-# - nodes the content of the nodes_list file
-# - my_uuid uuid of the current relay (self)
-# - shared_path the shared-files directory path
-# Returns true of false
-def shared_files_head(target_uuid, source_uuid, file_id, file_hash, nodes, my_uuid, shared_path):
- # where to find file
- path = file_directory(shared_path, nodes, my_uuid, target_uuid, source_uuid, file_id)
- filename = path + "/" + file_id
- metadata = filename + METADATA_EXTENSION
-
- # check if the file and signature exist
- if not os.path.isfile(filename) or not os.path.isfile(metadata):
- return False
-
- # check hash from metadata
- hash_value = get_metadata_hash(metadata)
- return hash_value == file_hash
-
-# =======================
-# Forward HEAD API call
-# =======================
-# Parameters:
-# - url where to forward to
-# Returns true of false
-def shared_files_head_forward(url):
- req = requests.head(url, verify=False)
- if req.status_code == 200:
- return True
- if req.status_code == 404:
- return False
- raise ValueError("ERROR from server:" + str(req.status_code))
-
-# ======================
-# Share folder HEAD API call
-# ======================
-# Parameters:
-# - file_name Name of the file in shared folder
-# - file_hash The hash to compare with, can be None or Empty
-# - hash_type hash algorithm
-# Returns correponding return code, 404 (file does not exists), 304 (hash is the same, not modified), 200 (file is different or no Hash sent, download)
-# 500 if hash_type is invalid
-def shared_folder_head(file_name, file_hash, hash_type):
- # where to find file
- file_path = os.path.join(SHARED_FOLDER, file_name)
- # check if the file and signature exist
- if not os.path.isfile(file_path):
- return 404
- else:
- if file_hash is None or file_hash == "":
- return 200
- try:
- hasher = hashlib.new(hash_type)
- except:
- return 500
- # check hash
- hash_value = get_shared_folder_hash(file_path, hasher)
- if hash_value == file_hash:
- return 304
- else:
- return 200
diff --git a/rudder-server-relay/SOURCES/relay-api/relay_api/views.py b/rudder-server-relay/SOURCES/relay-api/relay_api/views.py
deleted file mode 100644
index 147400af4..000000000
--- a/rudder-server-relay/SOURCES/relay-api/relay_api/views.py
+++ /dev/null
@@ -1,134 +0,0 @@
-from relay_api import app
-from relay_api.shared_files import shared_files_put, shared_files_head, shared_files_put_forward, shared_files_head_forward, shared_folder_head
-from relay_api.remote_run import remote_run_generic
-from relay_api.common import *
-
-from flask import Flask, jsonify, request, abort, make_response
-try:
- from StringIO import StringIO
-except ImportError:
- from io import StringIO
-import traceback
-
-from pprint import pprint
-
-NODESLIST_FILE = "/opt/rudder/etc/nodeslist.json"
-UUID_FILE = '/opt/rudder/etc/uuid.hive'
-API_DEBUGINFO = True
-POLICY_SERVER_FILE = "/var/rudder/cfengine-community/policy_server.dat"
-SHARED_FILES_PATH = "/var/rudder/shared-files"
-
-#################
-# API functions #
-#################
-
-@app.route('/shared-files///', methods=['PUT'])
-def put_file(target_uuid, source_uuid, file_id):
- try:
- nodes = get_nodes_list(NODESLIST_FILE)
- ttl = request.args.get('ttl', '')
- my_uuid = get_file_content(UUID_FILE)
- if target_uuid not in nodes:
- # forward the file if the node is unknown
- if my_uuid == "root":
- return format_response("Unknown UUID: "+target_uuid, 404)
- else:
- policy_server = get_file_content(POLICY_SERVER_FILE)
- url = "https://"+policy_server+"/rudder/relay-api/shared-files/" + target_uuid + "/" + source_uuid + "/" + file_id + "?ttl=" + ttl
- res = shared_files_put_forward(request.stream, url)
- else:
- # process the file if it is known
- filename = shared_files_put(target_uuid, source_uuid, file_id, request.stream, nodes, my_uuid, SHARED_FILES_PATH, ttl)
- if API_DEBUGINFO:
- res = "OK\nWritten to: " + filename + "\n"
- else:
- res = "OK\n"
- return format_response(res)
- except Exception as e:
- return format_error(e, API_DEBUGINFO)
-
-# mod_wsgi rewrites HEAD request to GET in some cases (don't know exactly when, but it depends on apache output filter, and breaks centos7 and not ubuntu 16)
-# Broken with wod_wsgi 3.4, works with mod_wsgi 4.3.0
-# GET requests here a rewritten HEAD, Real GET while be send at another location by a rewrite (cond and rule in rudder-apache-relay-ssl.conf file)
-# Some explanation: http://blog.dscpl.com.au/2009/10/wsgi-issues-with-http-head-requests.html
-# Some workaround: https://github.com/GrahamDumpleton/mod_wsgi/issues/2
-@app.route("/shared-folder/", methods=["HEAD", "GET"])
-def head_shared_folder(file_name):
- try:
- hash_type = "sha256"
- if "hash_type" in request.args:
- hash_type = request.args["hash_type"]
- file_hash = None
- if "hash" in request.args:
- file_hash = request.args["hash"]
- return_code = shared_folder_head(file_name, file_hash, hash_type)
- return format_response("", return_code)
-
- except Exception as e:
- print(traceback.format_exc())
- return format_error(e, API_DEBUGINFO)
-
-# mod_wsgi rewrites HEAD request to GET in some cases (don't know exactly when, but it depends on apache output filter, and breaks centos7 and not ubuntu 16)
-# Broken with wod_wsgi 3.2 and 3.4, works with mod_wsgi 4.3.0
-# GET requests here a rewritten HEAD, Real GET is never used on the shared-files api
-# Some explanation: http://blog.dscpl.com.au/2009/10/wsgi-issues-with-http-head-requests.html
-# Some workaround: https://github.com/GrahamDumpleton/mod_wsgi/issues/2
-@app.route('/shared-files///', methods=['HEAD','GET'])
-def head_file(target_uuid, source_uuid, file_id):
- try:
- nodes = get_nodes_list(NODESLIST_FILE)
- file_hash = request.args.get('hash', '')
- my_uuid = get_file_content(UUID_FILE)
- if target_uuid not in nodes:
- # forward the request if the node is unknown
- if my_uuid == "root":
- return format_response("Unknown UUID: "+target_uuid, 404)
- else:
- policy_server = get_file_content(POLICY_SERVER_FILE)
- url = "https://"+policy_server+"/rudder/relay-api/shared-files/" + target_uuid + "/" + source_uuid + "/" + file_id + "?hash=" + file_hash
- res = shared_files_head_forward(url)
- else:
- # process the request if it is known
- res = shared_files_head(target_uuid, source_uuid, file_id, file_hash, nodes, my_uuid, SHARED_FILES_PATH)
- if res:
- return format_response("", 200)
- else:
- return format_response("", 404)
- except Exception as e:
- print(traceback.format_exc())
- return format_error(e, API_DEBUGINFO)
-
-@app.route('/remote-run/all', methods=['POST'])
-def remote_run_all():
- try:
- nodes = get_nodes_list(NODESLIST_FILE)
- my_uuid = get_file_content(UUID_FILE)
- return remote_run_generic(nodes, my_uuid, None, True, request.form)
- except Exception as e:
- print(traceback.format_exc())
- return format_error(e, API_DEBUGINFO)
-
-@app.route('/remote-run/nodes', methods=['POST'])
-def remote_run_nodes():
- try:
- nodes = get_nodes_list(NODESLIST_FILE)
- my_uuid = get_file_content(UUID_FILE)
- return remote_run_generic(nodes, my_uuid, request.form['nodes'].split(','), False, request.form)
- except Exception as e:
- print(traceback.format_exc())
- return format_error(e, API_DEBUGINFO)
-
-@app.route('/remote-run/nodes/', methods=['POST'])
-def remote_run_node(node_id):
- try:
- nodes = get_nodes_list(NODESLIST_FILE)
- my_uuid = get_file_content(UUID_FILE)
- return remote_run_generic(nodes, my_uuid, [node_id], False, request.form)
- except Exception as e:
- print(traceback.format_exc())
- return format_error(e, API_DEBUGINFO)
-
-# main
-if __name__ == '__main__':
- app.run(debug = True)
-
diff --git a/rudder-server-relay/SOURCES/relay-api/requirements.txt b/rudder-server-relay/SOURCES/relay-api/requirements.txt
deleted file mode 100755
index 9a0599d42..000000000
--- a/rudder-server-relay/SOURCES/relay-api/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-flask==0.12.4
-requests==2.19.1
-pycrypto==2.6.1
diff --git a/rudder-server-relay/SOURCES/relay-api/run.py b/rudder-server-relay/SOURCES/relay-api/run.py
deleted file mode 100755
index be8265d9e..000000000
--- a/rudder-server-relay/SOURCES/relay-api/run.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!flask/bin/python
-
-# This file is only present for development/ local test and should not be used in production
-# To deploy ncf api you should use it with a virtual environment and a wsgi file
-# an example of this is available in ncf-api-virualenv package
-# Virtualenv defined should be in local directory flask
-
-import requests
-from relay_api import app
-
-app.run(debug = True)
diff --git a/rudder-server-relay/SOURCES/rudder-apache-relay-common.conf b/rudder-server-relay/SOURCES/rudder-apache-relay-common.conf
deleted file mode 100644
index 8564c9edb..000000000
--- a/rudder-server-relay/SOURCES/rudder-apache-relay-common.conf
+++ /dev/null
@@ -1,105 +0,0 @@
-DocumentRoot /var/www
-
-
- SSLOptions +StdEnvVars
-
-
- SSLOptions +StdEnvVars
-
-
-# We do not require mod_deflate as it is not strictly necessary
-
-
- # Enable gzip encoding on textual resources
- AddOutputFilterByType DEFLATE text/plain text/html text/xml text/javascript text/css
- AddOutputFilterByType DEFLATE application/xml application/xhtml+xml application/rss+xml image/svg+xml
- AddOutputFilterByType DEFLATE application/json application/javascript application/x-javascript
-
-
-
-# Expose the server UUID through http
-Alias /uuid /opt/rudder/etc/uuid.hive
-
- Require all granted
-
-
-# WebDAV share to receive inventories
-Alias /inventories /var/rudder/inventories/incoming
-
-
- DAV on
-
- AuthName "WebDAV Storage"
- AuthType Basic
- AuthUserFile /opt/rudder/etc/htpasswd-webdav-initial
-
- Require valid-user
-
- # rudder-networks-24.conf is automatically generated according to the hosts allowed by rudder.
- Include /opt/rudder/etc/rudder-networks-24.conf
-
-
- Require all denied
-
-
-
-
-# WebDAV share to receive inventories
-Alias /inventory-updates /var/rudder/inventories/accepted-nodes-updates
-
-
- DAV on
-
- AuthName "WebDAV Storage"
- AuthType Basic
- AuthUserFile /opt/rudder/etc/htpasswd-webdav
-
- Require valid-user
-
- # rudder-networks-24.conf is automatically generated according to the hosts allowed by rudder.
- Include /opt/rudder/etc/rudder-networks-24.conf
-
-
- Require all denied
-
-
-
-
-# Load relay-api
-WSGIScriptAlias /rudder/relay-api /opt/rudder/share/relay-api/relay-api.wsgi
-
-## Set directory access permissions
-
-
- # Allow access from anybody
- Require all granted
-
-
-
- # Allow access from anybody
- Require all granted
-
-
-
- # Allow access from anybody
- Require all granted
-
-
-# Disallow by default
-
- # WSGI parameters
- WSGIProcessGroup relay_api
- WSGIApplicationGroup %{GLOBAL}
-
- Require all denied
-
-
-
- # rudder-networks-24.conf is automatically generated according to the hosts allowed by rudder.
- Include /opt/rudder/etc/rudder-networks-24.conf
-
-
-
- # rudder-networks-policy-server-24.conf is automatically generated according to the policy server defined in rudder.
- Include /opt/rudder/etc/rudder-networks-policy-server-24.conf
-
diff --git a/rudder-server-relay/SOURCES/rudder-apache-relay-nossl.conf b/rudder-server-relay/SOURCES/rudder-apache-relay-nossl.conf
deleted file mode 100644
index 74dbc0f9f..000000000
--- a/rudder-server-relay/SOURCES/rudder-apache-relay-nossl.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-# Rudder webapp
-RewriteEngine on
-
-# If we are not currently connected via HTTP/S
-RewriteCond %{HTTPS} !=on
-
-# Restrict redirection to RudderRelay API
-RewriteCond %{REQUEST_URI} ^/rudder/relay-api/?
-
-# Redirect to HTTPS
-RewriteRule ^/(.*)$ https://%{SERVER_NAME}/$1 [R]
diff --git a/rudder-server-relay/SOURCES/rudder-apache-relay-ssl.conf b/rudder-server-relay/SOURCES/rudder-apache-relay-ssl.conf
deleted file mode 100644
index 1f5a89091..000000000
--- a/rudder-server-relay/SOURCES/rudder-apache-relay-ssl.conf
+++ /dev/null
@@ -1,46 +0,0 @@
-# Provide nodes policies
-# ----------------------
-
-RewriteEngine On
-
-
-# List of allowed certificates
-SSLCACertificateFile /opt/rudder/etc/ssl/ca.cert
-
-# Explanation
-# 1. The Rewriterule pattern is matched
-# Yes -> if so the result goes to $0,$1,$2
-# No -> no rewrite, no access to the files
-# 2. The RewriteCond is checked
-# -> Get client uuid from %{SSL:SSL_CLIENT_S_DN_UID}
-# -> Get requested uuid from the Rewriterule pattern ($1)
-# -> Generate a TestString of the form "="
-# -> Test the string against a regex that check that the left part is identical to the right part
-# 3. The Rewriterule is applied
-# -> final path is generated from the rule pattern
-RewriteCond "%{SSL:SSL_CLIENT_S_DN_UID}=$1" "^(.*?)=\1"
-RewriteRule /policies/(.*?)/(.*) /var/rudder/share/$1/$2
-
-# This is the basic configuration for sub-directories of /var/rudder/share
-
- SSLVerifyClient require
- SSLUserName SSL_CLIENT_S_DN_CN
- SSLRequireSSL
-
- # rudder-networks-24.conf is automatically
- # generated according to the hosts allowed by rudder.
- Include /opt/rudder/etc/rudder-networks-24.conf
-
-
-
-
- SSLVerifyClient require
- SSLUserName SSL_CLIENT_S_DN_CN
- SSLRequireSSL
-
- Include /opt/rudder/etc/rudder-networks-24.conf
-
-
-RewriteCond %{REQUEST_METHOD} =GET
-RewriteRule /rudder/relay-api/shared-folder/(.*) /var/rudder/configuration-repository/shared-files/$1
-
diff --git a/rudder-server-relay/SOURCES/rudder-networks-24.conf b/rudder-server-relay/SOURCES/rudder-networks-24.conf
deleted file mode 100644
index b66e80882..000000000
--- a/rudder-server-relay/SOURCES/rudder-networks-24.conf
+++ /dev/null
@@ -1 +0,0 @@
-Require all denied
diff --git a/rudder-server-relay/SOURCES/rudder-networks-policy-server-24.conf b/rudder-server-relay/SOURCES/rudder-networks-policy-server-24.conf
deleted file mode 100644
index 24968b58f..000000000
--- a/rudder-server-relay/SOURCES/rudder-networks-policy-server-24.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-Require ip 127.0.0.0/8
-Require ip ::1
diff --git a/rudder-server-relay/SOURCES/rudder-pkg b/rudder-server-relay/SOURCES/rudder-pkg
deleted file mode 100755
index 068cce8d0..000000000
--- a/rudder-server-relay/SOURCES/rudder-pkg
+++ /dev/null
@@ -1,416 +0,0 @@
-#!/usr/bin/python
-
-"""
-Rudder package manager
-
-Usage:
- rudder-pkg install-file ...
- rudder-pkg list
- rudder-pkg remove ...
- rudder-pkg rudder-postupgrade
- rudder-pkg check-compatibility
- rudder-pkg plugin save-status
- rudder-pkg plugin restore-status
- rudder-pkg plugin enable ...
- rudder-pkg plugin enable-all
- rudder-pkg plugin disable ...
- rudder-pkg plugin disable-all
-
-Options:
-
-Commands:
- install-file
- install a single package file into Rudder
-
- list
- list installed packages
-
- remove
- remove the given package from Rudder
-
- rudder-postupgrade
- execute plugins post install scripts (needed after a Rudder upgrade)
-
- check-compatibility
- disable plugins that are not compatible with current Rudder version
-
- plugin
- commands on plugin status
-"""
-
-# nice to have
-# rudder-pkg install package # from std dir / from repo
-# rudder-pkg upgrade package # from std dir / from repo
-
-from __future__ import print_function
-import sys
-sys.path.insert(0,"/opt/rudder/share/python")
-
-from pprint import pprint
-import argparse
-import json
-import os
-import tempfile
-import shutil
-import copy
-import re
-import docopt
-import sys
-import distutils.spawn
-from subprocess import Popen,PIPE
-
-p = Popen("rudder agent version", shell=True, stdout=PIPE)
-line = p.communicate()[0]
-m = re.match(r'Rudder agent (\d+\.\d+)\..*', line.decode('utf-8'))
-if m:
- RUDDER_VERSION=m.group(1)
-else:
- print("Cannot retrieve major version, ABORTING !")
- exit(1)
-DB = { "plugins": { } }
-DB_DIRECTORY = '/var/rudder/packages'
-# Contains the installed package database
-DB_FILE = DB_DIRECTORY + '/index.json'
-# Contains known incompatible plugins (installed by the relay package)
-# this is a simple list with names od the form "plugin_name-version"
-COMPATIBILITY_DB = { "incompatibles": [] }
-COMPATIBILITY_FILE = DB_DIRECTORY + '/compatible.json'
-
-# Plugins specific resources
-PLUGINS_CONTEXT_XML = "/opt/rudder/share/webapps/rudder.xml"
-
-
-# Run a command in a shell like a script would do
-# And inform the user of its execution
-def shell(command, comment=None, keep_output=False, fail_exit=True, keep_error=False):
- if comment is not None:
- print(comment)
- print(" $ " + command)
- if keep_output or keep_error:
- if keep_output:
- keep_out = PIPE
- else:
- keep_out = None
- if keep_error:
- keep_err = PIPE
- else:
- keep_err = None
- process = Popen(command, stdout=keep_out, stderr=keep_err, shell=True, universal_newlines=True)
- output, error = process.communicate()
- retcode = process.poll()
- else: # keep tty management and thus colors
- process = Popen(command, shell=True)
- retcode = process.wait()
- output = None
- error = None
- if fail_exit and retcode != 0:
- exit(retcode)
- return (retcode, output, error)
-
-
-def fail(message, code=1):
- print(message)
- exit(code)
-
-
-# Indexing methods
-def db_load():
- """ Load the index file into a global variable """
- global DB, COMPATIBILITY_DB
- if os.path.isfile(DB_FILE):
- with open(DB_FILE) as fd:
- DB = json.load(fd)
- if os.path.isfile(COMPATIBILITY_FILE):
- with open(COMPATIBILITY_FILE) as fd:
- COMPATIBILITY_DB = json.load(fd)
-
-def db_save():
- """ Save the index into a file """
- with open(DB_FILE, 'w') as fd:
- json.dump(DB, fd)
-
-
-def rpkg_metadata(package_file):
- (_, output, _) = shell("ar p '" + package_file + "' metadata", keep_output=True)
- return json.loads(output)
-
-
-def package_check(metadata):
- # we can only install pugins at the moment
- if 'type' not in metadata or metadata['type'] != 'plugin':
- fail("Package type not supported")
- # sanity checks
- if 'name' not in metadata:
- fail("Package name undefined")
- name = metadata['name']
- if 'version' not in metadata:
- fail("Package version undefined")
- # incompatibility check
- if metadata['type'] == 'plugin':
- if not check_plugin_compatibility(metadata):
- fail("Package incompatible with this Rudder version, please use a more recent one")
- # do not compare with exiting version to allow people to reinstall or downgrade
- return name in DB['plugins']
-
-
-def check_plugin_compatibility(metadata):
- # check that the given version is compatible with Rudder one
- match = re.match(r'(\d+\.\d+)-(\d+)\.(\d+)', metadata['version'])
- if not match:
- fail("Invalid package version " + metadata['version'])
- rudder_version = match.group(1)
- major_version = match.group(2)
- minor_version = match.group(3)
- if rudder_version != RUDDER_VERSION:
- print("Package '"+ metadata['name'] +"' is not compatible with current version of rudder")
- return False
- # check specific constraints
- full_name = metadata['name'] + '-' + metadata['version']
- if full_name in COMPATIBILITY_DB['incompatibles']:
- return False
- return True
-
-
-
-def install_dependencies(metadata):
- # not supported yet
- has_depends = False
- depends_printed = False
- if "depends" in metadata:
- for system in metadata["depends"]:
- if system == "binary":
- for executable in metadata["depends"][system]:
- if distutils.spawn.find_executable(executable) is None:
- print("The binary " + executable + " was not found on the system, you must install it before installing " + metadata['name'])
- return False
- else:
- has_depends = True
- if not depends_printed:
- print("This package depends on the following")
- depends_printed = True
- print(" on " + system + " : " + ", ".join(metadata["depends"][system]))
- if has_depends:
- print("It is up to you to make sure those dependencies are installed")
- return True
-
-
-def extract_scripts(metadata,package_file):
- package_dir = DB_DIRECTORY + "/" + metadata["name"]
- shell("mkdir -p " + package_dir + "; ar p '" + package_file + "' scripts.txz | tar xJ --no-same-owner -C " + package_dir)
- return package_dir
-
-
-def run_script(name, script_dir, exist):
- script = script_dir + "/" + name
- if os.path.isfile(script):
- if exist is None:
- param = ""
- elif exist:
- param = "upgrade"
- else:
- param = "install"
- shell(script + " " + param)
-
-
-def jar_status(name, enable):
- global jetty_needs_restart
- text = open(PLUGINS_CONTEXT_XML).read()
- def repl(match):
- enabled = [x for x in match.group(1).split(',') if x != name and x != '']
- pprint(enabled)
- if enable:
- enabled.append(name)
- plugins = ','.join(enabled)
- return '' + plugins + ''
- text = re.sub(r'(.*?)', repl, text)
- open(PLUGINS_CONTEXT_XML, "w").write(text)
- jetty_needs_restart = True
-
-
-def remove_files(metadata):
- for filename in reversed(metadata['files']):
- # ignore already removed files
- if not os.path.exists(filename):
- print("Skipping removal of " + filename + " as it does not exist")
- continue
-
- # remove old files
- if filename.endswith('/'):
- try:
- os.rmdir(filename)
- except OSError:
- pass
- else:
- os.remove(filename)
-
-
-def install(metadata, package_file, exist):
- if exist:
- remove_files(DB['plugins'][metadata['name']])
- # add new files
- files = []
- for tarfile in metadata['content']:
- dest = metadata['content'][tarfile]
- (_, file_list, _) = shell("mkdir -p " + dest + "; ar p '" + package_file + "' " + tarfile + " | tar xJv --no-same-owner -C " + dest, keep_output=True)
- files.append(dest+'/')
- files.extend([ dest + '/' + x for x in file_list.split("\n") if x != ''])
-
- metadata['files'] = files
- # update db
- DB['plugins'][metadata['name']] = metadata
- db_save()
-
-
-## Package commands
-
-def install_file(package_files):
- for package_file in package_files:
- print("Installing " + package_file)
- # First, check if file exists
- if not os.path.isfile(package_file):
- print("Error: Package file " + package_file + " does not exist")
- exit(1)
- metadata = rpkg_metadata(package_file)
- exist = package_check(metadata)
- # As dependencies are only displayed messages for now, wait until the end to make them visible.
- # This should be moved before actual installation once implemented.
- if not install_dependencies(metadata):
- exit(1)
- if exist:
- print("The package is already installed, I will upgrade it.")
- script_dir = extract_scripts(metadata, package_file)
- run_script("preinst", script_dir, exist)
- install(metadata, package_file, exist)
- run_script("postinst", script_dir, exist)
- if metadata['type'] == 'plugin' and 'jar-files' in metadata:
- for j in metadata['jar-files']:
- jar_status(j, True)
-
-
-def package_list():
- for p in DB["plugins"].keys():
- print(p + "\t" + DB["plugins"][p]["version"])
-
-
-def remove(package_names):
- for package_name in package_names:
- print("Removing " + package_name)
- if package_name not in DB["plugins"]:
- fail("This package is not installed. Aborting!", 2)
- script_dir = DB_DIRECTORY + "/" + package_name
- metadata = DB["plugins"][package_name]
- if metadata['type'] == 'plugin' and 'jar-files' in metadata:
- for j in metadata['jar-files']:
- jar_status(j, False)
- run_script("prerm", script_dir, None)
- remove_files(metadata)
- run_script("postrm", script_dir, None)
- shutil.rmtree(script_dir)
- del DB["plugins"][package_name]
- db_save()
-
-
-def check_compatibility():
- global jetty_needs_restart
- for p in DB["plugins"]:
- metadata = DB["plugins"][p]
- if not check_plugin_compatibility(metadata):
- print("Plugin " + p + " is not compatible with rudder anymore, disabling it.")
- if 'jar-files' in metadata:
- for j in metadata['jar-files']:
- jar_status(j, False)
- print("Please install a new version of " + p + " to enable it again.")
- print("")
- jetty_needs_restart = True
-
-
-def plugin_save_status():
- enabled = []
-
- if not os.path.exists(PLUGINS_CONTEXT_XML):
- return
-
- text = open(PLUGINS_CONTEXT_XML).read()
- match = re.search(r'(.*?)', text)
- if match:
- enabled = match.group(1).split(',')
- for p in DB["plugins"]:
- metadata = DB["plugins"][p]
- if 'jar-files' in metadata:
- for j in metadata['jar-files']:
- if j in enabled:
- print("enabled " + j)
- else:
- print("disabled " + j)
-
-
-def plugin_restore_status():
- lines = sys.stdin.readlines()
- for line in lines:
- line = line.strip()
- if line.startswith("enabled "):
- print("enable " + line.split(' ')[1])
- jar_status(line.split(' ')[1], True)
- if line.startswith("disabled "):
- jar_status(line.split(' ')[1], False)
- check_compatibility()
-
-
-def rudder_postupgrade():
- for plugin in DB["plugins"]:
- script_dir = DB_DIRECTORY + "/" + plugin
- run_script("postinst", script_dir, True)
-
-def plugin_disable_all():
- plugin_status(DB["plugins"].keys(), False)
-
-
-def plugin_enable_all():
- plugin_status(DB["plugins"].keys(), True)
-
-def plugin_status(plugins, status):
- for plugin in plugins:
- if status:
- print("Enabling " + plugin)
- else:
- print("Disabling " + plugin)
- if plugin not in DB["plugins"]:
- fail("Unknown plugin " + plugin)
- metadata = DB["plugins"][plugin]
- if 'jar-files' in metadata:
- for j in metadata['jar-files']:
- jar_status(j, status)
-
-
-## MAIN
-if __name__ == "__main__":
- args = docopt.docopt(__doc__)
- db_load()
- jetty_needs_restart = False
-
- if args['install-file']:
- install_file(args[''])
- elif args['list']:
- package_list()
- elif args['remove']:
- remove(args[''])
- elif args['rudder-postupgrade']:
- rudder_postupgrade()
- elif args['check-compatibility']:
- check_compatibility()
- elif args['plugin']:
- if args['save-status']:
- plugin_save_status()
- elif args['restore-status']:
- plugin_restore_status()
- elif args['enable']:
- plugin_status(args[''], True)
- elif args['enable-all']:
- plugin_enable_all()
- elif args['disable']:
- plugin_status(args[''], False)
- elif args['disable-all']:
- plugin_disable_all()
-
- if jetty_needs_restart:
- shell("service rudder-jetty restart", "Restarting jetty")
diff --git a/rudder-server-relay/SOURCES/rudder-relay-apache b/rudder-server-relay/SOURCES/rudder-relay-apache
deleted file mode 100644
index 360e7fca0..000000000
--- a/rudder-server-relay/SOURCES/rudder-relay-apache
+++ /dev/null
@@ -1,5 +0,0 @@
-# Apache modules
-APACHE_MODULES="${APACHE_MODULES} dav dav_fs ssl version wsgi filter deflate"
-
-# Apache configuration flags
-APACHE_SERVER_FLAGS="${APACHE_SERVER_FLAGS} SSL"
diff --git a/rudder-server-relay/SOURCES/rudder-relay.cron b/rudder-server-relay/SOURCES/rudder-relay.cron
deleted file mode 100644
index 9d7879476..000000000
--- a/rudder-server-relay/SOURCES/rudder-relay.cron
+++ /dev/null
@@ -1,5 +0,0 @@
-# Cron file for Rudder relay
-#
-
-*/5 * * * * root /opt/rudder/share/relay-api/cleanup.sh >/dev/null
-
diff --git a/rudder-server-relay/SOURCES/rudder-relay.fc b/rudder-server-relay/SOURCES/rudder-relay.fc
deleted file mode 100644
index fe47b7168..000000000
--- a/rudder-server-relay/SOURCES/rudder-relay.fc
+++ /dev/null
@@ -1,5 +0,0 @@
-/var/rudder/inventories/accepted-nodes-updates gen_context(system_u:object_r:httpd_sys_rw_content_t,s0)
-/var/rudder/inventories/incoming gen_context(system_u:object_r:httpd_sys_rw_content_t,s0)
-/var/log/rudder/apache2(/.*)? gen_context(system_u:object_r:httpd_log_t,s0)
-/opt/rudder/etc/uuid.hive gen_context(system_u:object_r:httpd_sys_content_t,s0)
-
diff --git a/rudder-server-relay/SOURCES/rudder-relay.sudo b/rudder-server-relay/SOURCES/rudder-relay.sudo
deleted file mode 100644
index 0392e33b7..000000000
--- a/rudder-server-relay/SOURCES/rudder-relay.sudo
+++ /dev/null
@@ -1,4 +0,0 @@
-# Allow the relay API to trigger remote runs
-rudder ALL = NOPASSWD: /opt/rudder/bin/rudder remote run *
-# Allow the relay API to trigger local runs
-rudder ALL = NOPASSWD: /opt/rudder/bin/rudder agent run *
diff --git a/rudder-server-relay/SOURCES/rudder-relay.te b/rudder-server-relay/SOURCES/rudder-relay.te
deleted file mode 100644
index 6fbdc24d8..000000000
--- a/rudder-server-relay/SOURCES/rudder-relay.te
+++ /dev/null
@@ -1,12 +0,0 @@
-# Source file for rudder-webapp.pp
-# # Generate rudder-webapp.pp by running:
-# # make -f /usr/share/selinux/devel/Makefile
-
-module rudder-relay 1.0;
-
-require {
- type httpd_log_t;
- type httpd_sys_rw_content_t;
- type httpd_sys_content_t;
-}
-
diff --git a/rudder-server-relay/SOURCES/rudder-vhost.conf b/rudder-server-relay/SOURCES/rudder-vhost.conf
deleted file mode 100644
index cb5311f70..000000000
--- a/rudder-server-relay/SOURCES/rudder-vhost.conf
+++ /dev/null
@@ -1,40 +0,0 @@
-# Set up a WSGI serving process common to ssl and non ssl vhost
-WSGIDaemonProcess relay_api threads=5 user=rudder group=rudder
-WSGISocketPrefix /var/run/wsgi
-
-
-
- ServerAdmin webmaster@localhost
-
- # Logs
- LogLevel warn
- CustomLog /var/log/rudder/apache2/access.log combined
- ErrorLog /var/log/rudder/apache2/error.log
-
- # Include Rudder common vhost definitions
- Include /opt/rudder/etc/rudder-apache-*-common.conf
-
- IncludeOptional /opt/rudder/etc/rudder-apache-*-nossl.conf
-
-
-
-
- ServerAdmin webmaster@localhost
-
- # Logs
- LogLevel warn
- CustomLog /var/log/rudder/apache2/access.log combined
- ErrorLog /var/log/rudder/apache2/error.log
-
- # SSL Engine Switch:
- # Enable/Disable SSL for this virtual host.
- SSLEngine on
-
- SSLCertificateFile /opt/rudder/etc/ssl/rudder.crt
- SSLCertificateKeyFile /opt/rudder/etc/ssl/rudder.key
-
- # Include Rudder common vhost definitions
- Include /opt/rudder/etc/rudder-apache-*-common.conf
-
- IncludeOptional /opt/rudder/etc/rudder-apache-*-ssl.conf
-
diff --git a/rudder-server-relay/SOURCES/ssl/ca.cert b/rudder-server-relay/SOURCES/ssl/ca.cert
deleted file mode 100644
index e69de29bb..000000000