Mapping Engine CLI

Implementation of a command line wrapped build on top of mapping engine.
Its main goal is checking effects of input parsed by RuleProcessor with
set of provided mapping rules. User must provide two files: a) rules
file with proper JSON with mapping rules (identical to those uploaded to
the server) b) a file with key-value set of environ-like parameters.

Basic usage:

$ keystone-manage mapping_engine --help
$ keystone-manage mapping_engine --rules <path> --input <path>

Upon successful execution program outputs to the stdout a JSON structure
with effective objects like user, group_ids and user_names.

Implements: bp mapping-engine-tester
Change-Id: Ia4b2e617692ebb42693db6d335985dcb6a0969e1
This commit is contained in:
Marek Denis 2015-06-03 17:04:52 +02:00
parent f6c01dd167
commit 039b0bd9a9
2 changed files with 93 additions and 0 deletions

View File

@ -46,6 +46,7 @@ Available commands:
* ``fernet_rotate``: Rotate keys in the Fernet key repository.
* ``fernet_setup``: Setup a Fernet key repository.
* ``mapping_purge``: Purge the identity mapping table.
* ``mapping_engine``: Test your federation mapping rules.
* ``pki_setup``: Initialize the certificates used to sign tokens.
* ``saml_idp_metadata``: Generate identity provider metadata.
* ``ssl_setup``: Generate certificates for SSL.

View File

@ -19,6 +19,7 @@ import os
from oslo_config import cfg
from oslo_log import log
from oslo_serialization import jsonutils
import pbr.version
from keystone import backends
@ -544,6 +545,96 @@ class SamlIdentityProviderMetadata(BaseApp):
print(metadata.to_string())
class MappingEngineTester(BaseApp):
"""Execute mapping engine locally."""
name = 'mapping_engine'
@staticmethod
def read_rules(path):
try:
with open(path) as file:
return jsonutils.load(file)
except ValueError as e:
raise SystemExit(_('Error while parsing rules '
'%(path)s: %(err)s') % {'path': path, 'err': e})
@staticmethod
def read_file(path):
try:
with open(path) as file:
return file.read().strip()
except IOError as e:
raise SystemExit(_("Error while opening file "
"%(path)s: %(err)s") % {'path': path, 'err': e})
@staticmethod
def normalize_assertion(assertion):
def split(line):
try:
k, v = line.split(':', 1)
return k.strip(), v.strip()
except ValueError as e:
msg = _("Error while parsing line: '%(line)s': %(err)s")
raise SystemExit(msg % {'line': line, 'err': e})
assertion = assertion.split('\n')
assertion_dict = {}
prefix = CONF.command.prefix
for line in assertion:
k, v = split(line)
if prefix:
if k.startswith(prefix):
assertion_dict[k] = v
else:
assertion_dict[k] = v
return assertion_dict
@classmethod
def main(cls):
from keystone.contrib.federation import utils as mapping_engine
if not CONF.command.engine_debug:
mapping_engine.LOG.logger.setLevel('WARN')
rules = MappingEngineTester.read_rules(CONF.command.rules)
mapping_engine.validate_mapping_structure(rules)
assertion = MappingEngineTester.read_file(CONF.command.input)
assertion = MappingEngineTester.normalize_assertion(assertion)
rp = mapping_engine.RuleProcessor(rules['rules'])
print(jsonutils.dumps(rp.process(assertion), indent=2))
@classmethod
def add_argument_parser(cls, subparsers):
parser = super(MappingEngineTester,
cls).add_argument_parser(subparsers)
parser.add_argument('--rules', default=None, required=True,
help=("Path to the file with "
"rules to be executed. "
"Content must be a proper JSON structure, "
"with a top-level key 'rules' and "
"corresponding value being a list."))
parser.add_argument('--input', default=None, required=True,
help=("Path to the file with input attributes. "
"The content consists of ':' separated "
"parameter names and their values. "
"There is only one key-value pair per line. "
"A ';' in the value is a separator and then "
"a value is treated as a list. Example:\n "
"EMAIL: me@example.com\n"
"LOGIN: me\n"
"GROUPS: group1;group2;group3"))
parser.add_argument('--prefix', default=None,
help=("A prefix used for each environment "
"variable in the assertion. For example, "
"all environment variables may have the "
"prefix ASDF_."))
parser.add_argument('--engine-debug',
default=False, action="store_true",
help=("Enable debug messages from the mapping "
"engine."))
CMDS = [
DbSync,
DbVersion,
@ -551,6 +642,7 @@ CMDS = [
FernetRotate,
FernetSetup,
MappingPurge,
MappingEngineTester,
PKISetup,
SamlIdentityProviderMetadata,
SSLSetup,