Package: feudalAdapter
FEUDAL Client AdapterThis code implements the adapter for FEUDAL to communicate with various services, called "backends".Distributed with the adapter are backends forBWIDMandUNIX.InstallationFrom PyPipip install feudalAdapterFrom SourceGit clone:git clone git@git.scc.kit.edu:feudal/feudalAdapterLdf.gitBuild package:cd feudalAdapterLDF; ./setup.py sdistInstall package:pip install dist/feudalAdapter-$version.tar.gzConfigurationThe config file contains both the generic config, as well as for specific backends.Configuration TemplateSeefeudal_adapter_template.confConfig file search pathThe config file feudal_adapter.conf will be searched in several places. Once
it is found no further config files will be considered:If the commandline argument--configis specified, that location is used.If thefeudal_globalconfmechanism is used, it is used. In case there is
also a commandline argument specified, theglobaldconfhas precedenceIf those dont work: the environment variableFEUDAL_ADAPTER_CONFIGis usedIf that does not work, these files will be tried by default:feudal_adapter.conf$HOME/.config/feudal_adapter.conf$HOME/.config/feudal/feudal_adapter.conf/etc/feudal/feudal_adapter.confInput and OutputThe FeudalAdapter is designed to work with feudalClient and hence expects
specific json on stdin, and produces specific json on stdout.The was initially definedhere (feudalScripts)An extension is implemented, to work withMotley Cue,
therefore, we feudalAdapterLDF supports additional targets. Most of these
targets do not require the full userinfo to be passed along:TargetDescriptionInput requiredOptional inputdeployedMake sure the user exists on the systemFull userinfossh-keysnot_deployedMake sure the user is not on the systemsub+issget_statusGet the current status of the user without changing itA more detailed view of all the supported user states, as well as actions leading to these states, can be found instates.md.DevelopmentDebuggingFor development you can use the included json files in the examples folder
and pass them on stdin:cd[...]/feudalAdapterLDFexportPYTHONPATH=`pwd`exportLOG=DEBUG

catexamples/marcus-deploy.json|./ldf_adapter/interface.pyDebugging with FeudalClient:For debugging, run the feudalClient with:LOG=DEBUGfeudalClient-c~/.config/feudal/client.json--debug-scriptsDevelopmentfeudalAdapter can also be used as a library; For that you can use the
feudal_globalconfig to keep it from parsing your commandline paramenters:fromfeudal_globalconfigimportglobalconfigglobalconfig.config['CONFIGFILE']="/etc/feudal/feudal_adapter_mailping.conf"globalconfig.config['parse_commandline_args']=Falsefromldf_adapterimportUserSupported BackendsBackends are simply python modules. The supported backends are in thebackendsfolder.The backend is configured in the main config file, and may create and use
its own sections therein.[ldf_adapter]
backend = my_backend

[backend.my_backend]
foo = bar
# Configuration for your backend goes hereSupported backends:local UNIXLDAPbwIDMDevelopmentTo add a new backend:extend theUserandGroupclasses in thegeneric backendby implementing all the required abstract methodsthe extended classesmustalso be namedUserandGroupplace the classes in a python file inldf_adapter/backend(e.g.my_backend.py)the name of the backend will be the name of the file, and it will be loaded dynamically when used (e.g.my_backend)use the new backend by setting thebackendin the[ldf_adapter]section in the config file to your new backend name[ldf_adapter]
backend = my_backendif you need to add any configuration for your backend, add a new section in the config file:[backend.my_backend]
key1 = value1
key2 = value2define types and default values for the configuration inldf_adapter/config.py(check out the comments on adding a new section)you will then be able to use these configuration values in your backend with:from ldf_adapter.config import CONFIG
print("key1: ", CONFIG.backend.my_backend.key1)
print("key2: ", CONFIG.backend.my_backend.key2)Approval workflowThefeudalAdapteralso supports a so-calledapproval workflow, which allows site admins to oversee all deployment requests from users, and accept or reject them manually. This workflow uses additional user states (pending,rejected), as well as a local database for storing deployment requests.How it works:on a request to reach thedeployedstate, a local user (+ its groups) is "reserved" by storing this deployment request in the local databasethe response to this request is a "pending" userthe site admin is notified of this request (currently supported notification systems:email)for local_unix backend, notification contains all necessaryuseradd,usermodcommandsfor ldap backend, notification contains LDIF representationthe site admin can then accept or reject this request by manually adding the user or, if supported, using "accepted"/"rejected" as state_targetusers are not notified of acceptance/rejectionsubsequent deployment requests for existing users check if there have been changes to the userinfo (e.g. group memberships) and notify the admin only when updates are necessary.ConfigurationEnable and configure the approval in the config file:[approval]
enabled = True

### user db location -- default: /var/lib/feudal/pending_users.db
# currently, only sqlite is used as db for pending requests.
# user_db_location = /var/lib/feudal/pending_users.db

### notifier -- default: email
# how to notify admins of incoming deployment requests; supported: email
# to test that the configuration works, try `feudal-adapter --test`
notifier = emailTheemailnotifier will need to be configured, as it will not work out of the box. You'll need an SMTP server for sending emails. If your organisation does not provide one, you can usegmail(requires you to create and provide an app password).A few more configs:sent_from: the address that the emails will be sent fromadmin_email: the email of the site admin that will approve the requeststemplates_dir: the folder where the email templates are located. Please make sure that the folder exists and contains all the files fromtemplates. When installingfeudalAdaptervia pip, this folder is installed atetc/feudal/templates, relative to your python path. You are free to modify the content of the files.To test that your email notification system works, run:feudal-adapter --testUnit TestsThere are unit tests, located undertests(The package structure intestscorresponds to
that of the main package). To run the tests, just do:toxIntegration with Feudal:Edit the FEUDAL Client config file (e.g.~/.config/feudal/client.yaml) to include:services:"mclientservice":"name":"DemoAdapter""description":"Workssowell""command":"feudal-adapter--conf/etc/feudal/feudal_adapter.conf"This goes away sooner or laterRegApp REST InterfaceThe rest interface of the LDAP facade supports the calls documented here.For configuration we use these environment variablesUSER="username"
PASS="password"
ENDP="https://bwidm-test.scc.kit.edu/rest"Create usercurl --basic -u $USER:$PASS \
    -H "Content-Type: application/json" \
    -X POST -d '{"externalId":"marcus-test-1"}' \
    $ENDP/external-user/create

Benutzer anlegen:

Zum Anlegen reicht eine externalId. Mehr Werte sind im Grunde nicht
notwendig. Allerdings kann man mit diesem Benutzer dann noch nicht viel
anstellen. Die externalId stellt immer das prim??re
Identifizierungsmerkmal dar. Sie ist nicht ??nderbar.Update userUse this call to update the user object and to rewrite the generic store in the LDF.curl --basic -u $USER:$PASS \
    -H "Content-Type: application/json" 
    -X POST -d ' \
{"externalId":"test0002","eppn":"test0002@hdf.de","email":"test-diezweite@kit.edu","genericStore": { "ssh_key": "[{'value': 'ssh-rsa AA[..]0R', 'name': 'unity_key'}]" },"surName":"Testfamilie","givenName":"Hans","primaryGroup":{"id":1002637},"attributeStore":{"urn:oid:0.9.2342.19200300.100.1.1":"test0002","http://bw idm.de/bwidmOrgId":"hdf"}}
' \
    $ENDP/external-user/updateThe above, but reformatted:curl --basic -u $USER:$PASS 
    -H "Content-Type: application/json" 
    -X POST -d ' 
        {
          "externalId": "test0002",
          "eppn": "test0002@hdf.de",
          "email": "test-diezweite@kit.edu",
          "genericStore": {
            "ssh_key": "[{'value': 'ssh-rsa AA[..]0R', 'name': 'unity_key'}]"
          },
          "surName": "Testfamilie",
          "givenName": "Hans",
          "primaryGroup": {
            "id": 1002637
          },
          "attributeStore": {
            "urn:oid:0.9.2342.19200300.100.1.1": "test0002",
            "http://bw idm.de/bwidmOrgId": "hdf"
          }
        }
    ' 
    $ENDP/external-user/updateregister user for servicecurl --basic -u $USER:$PASS\
    $ENDP/external-reg/register/externalId/test0002/ssn/sshtestBenutzer für einen Dienst registrieren:
curl --basic -u $USER:$PASS $ENDP/external-reg/register/externalId/test0002/ssn/sshtestDabei ist es notwendig, dass die vom Dienst geforderten Attribute gesetzt sind. Das ist bei LDAP basierten Diensten normalerweise:EPPNE-Mail-AdresseprimaryGroupsurName, givenName (optional)attributeStore:
** urn:oid:0.9.2342.19200300.100.1.1 (Unix UserId - Anmeldename)
**http://bwidm.de/bwidmOrgId(soll "hdf", bzw. konfigurierbar sein)Der Anmeldename des Benutzers setzt sich nachher aus orgId und UserId zusammen. Also z.B. hdf_test0002Find user by unix user namecurl --basic -u $USER:$PASS $ENDP/external-user/find/attribute/urn:oid:0.9.2342.19200300.100.1.1/marcusWill return multiple entries for different externalId . This is because multiple externalId can be
mapped to the same unix account.Example output[
  {
    "id": 1007486,
    "createdAt": 1531327592699,
    "updatedAt": 1533732759215,
    "version": 7,
    "attributeStore": {
      "urn:oid:0.9.2342.19200300.100.1.1": "marcus",
      "http://bwidm.de/bwidmOrgId": "hdf"
    },
    "genericStore": {
      "ssh_key": "[{'value': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4vjkJr6H6eXKE9+dj4epCrcSUQRFih1603/SjJKIA3cpWt0O5TC4qJCQwOcvFXdjCu0Y1YUKrUlmV0D9fezbqNrSEZ30gT5YLhawUT6LukMTKfNLxa5wM7jzAlmhJ4obadTE5G5qpAGz5SbgHRfPdTlctpqmmFeyN/Rw4lgzoJ8+zHFyp2VPB7rCaUdsS+48lkVhYtlIDBogdRLAZp8MpSeHZFjHfpq+XDhHXdKnEtETV2+IQfMxRBj6Bpw7wwWpIkSQuf4VDHTAhb6+KjcBg/TBc46CekKzF6gtKImZZNVIzEXuAW2prHmQRh72+oQFMqhVcnRmDOWGwBEvXzT0R marcus@tuna2013', 'name': 'unity_key'}]"
    },
    "eppn": "Hardt@unity-hdf",
    "email": "no@email.provided",
    "givenName": "Marcus",
    "surName": "Hardt",
    "uidNumber": 900094,
    "emailAddresses": [],
    "primaryGroup": {
      "id": 1002637,
      "createdAt": 1525327969976,
      "updatedAt": 1525327969976,
      "version": 0,
      "name": "hdf-test",
      "gidNumber": 500573,
      "parents": [],
      "users": null
    },
    "secondaryGroups": [],
    "userStatus": "ACTIVE",
    "externalId": "hdf_61230996-664f-4422-9caa-76cf086f0d6c@unity-hdf"
  },
  {
    "id": 1013939,
    "createdAt": 1536046109021,
    "updatedAt": 1542101421071,
    "version": 8,
    "attributeStore": {
      "urn:oid:0.9.2342.19200300.100.1.1": "marcus",
      "http://bwidm.de/bwidmOrgId": "hdf"
    },
    "genericStore": {
      "ssh_key": "[{'value': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4vjkJr6H6eXKE9+dj4epCrcSUQRFih1603/SjJKIA3cpWt0O5TC4qJCQwOcvFXdjCu0Y1YUKrUlmV0D9fezbqNrSEZ30gT5YLhawUT6LukMTKfNLxa5wM7jzAlmhJ4obadTE5G5qpAGz5SbgHRfPdTlctpqmmFeyN/Rw4lgzoJ8+zHFyp2VPB7rCaUdsS+48lkVhYtlIDBogdRLAZp8MpSeHZFjHfpq+XDhHXdKnEtETV2+IQfMxRBj6Bpw7wwWpIkSQuf4VDHTAhb6+KjcBg/TBc46CekKzF6gtKImZZNVIzEXuAW2prHmQRh72+oQFMqhVcnRmDOWGwBEvXzT0R marcus@tuna2013-unity', 'name': 'unity_key'}, {'value': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCh3jF9KUaJXqbnaqaHwGmgXIes0nQMqYFx1N3sa4nfbhyBipjSfCyv3yGHO8yciPIjWGTwPUD+HhczXSOJMGruBwwHCKq2vhrdsWJy/bsCs1iBQN9d0oUyPtn+48UcY6ceZfwGcM3KIOxxMu/nzvgZXme53TXSAWH6VASrCjBSSZ/9JvDaxrgVudOW6a3LE6AZMDsi4YEhdP7FTn4wpFVyCpkIttETX26qDAbD2UuR0KNa42yyDdbzu+3ZAoYmkyCcthgsesEm692r+F6TJnBLFVVAtGiQ21cwM8wKgYUDVMZknBo8QKiLvYhvs3zuCVVKBANYqMCOeO2Z3dQem00t root@tuna2013', 'name': 'marcus'}]"
    },
    "eppn": "hardt@unity-hdf",
    "email": "marcus.hardt@kit.edu",
    "givenName": "Marcus",
    "surName": "Hardt",
    "uidNumber": 900105,
    "emailAddresses": [],
    "primaryGroup": {
      "id": 1009662,
      "createdAt": 1533559253589,
      "updatedAt": 1533559253589,
      "version": 0,
      "name": "mytestcollab",
      "gidNumber": 500593,
      "parents": [],
      "users": null
    },
    "secondaryGroups": [],
    "userStatus": "ACTIVE",
    "externalId": "hdf_ec0c370f-39a6-4c15-a94e-cf56367e2414@unity-hdf"
  }
]Find user by external idcurl --basic -u $USER:$PASS $ENDP/external-user/find/externalId/hdf_61230996-664f-4422-9caa-76cf086f0d6c@unity-hdfExample output{
  "id": 1007486,
  "createdAt": 1531327592699,
  "updatedAt": 1533732759215,
  "version": 7,
  "attributeStore": {
    "urn:oid:0.9.2342.19200300.100.1.1": "marcus",
    "http://bwidm.de/bwidmOrgId": "hdf"
  },
  "genericStore": {
    "ssh_key": "[{'value': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4vjkJr6H6eXKE9+dj4epCrcSUQRFih1603/SjJKIA3cpWt0O5TC4qJCQwOcvFXdjCu0Y1YUKrUlmV0D9fezbqNrSEZ30gT5YLhawUT6LukMTKfNLxa5wM7jzAlmhJ4obadTE5G5qpAGz5SbgHRfPdTlctpqmmFeyN/Rw4lgzoJ8+zHFyp2VPB7rCaUdsS+48lkVhYtlIDBogdRLAZp8MpSeHZFjHfpq+XDhHXdKnEtETV2+IQfMxRBj6Bpw7wwWpIkSQuf4VDHTAhb6+KjcBg/TBc46CekKzF6gtKImZZNVIzEXuAW2prHmQRh72+oQFMqhVcnRmDOWGwBEvXzT0R marcus@tuna2013', 'name': 'unity_key'}]"
  },
  "eppn": "Hardt@unity-hdf",
  "email": "no@email.provided",
  "givenName": "Marcus",
  "surName": "Hardt",
  "uidNumber": 900094,
  "emailAddresses": [],
  "primaryGroup": {
    "id": 1002637,
    "createdAt": 1525327969976,
    "updatedAt": 1525327969976,
    "version": 0,
    "name": "hdf-test",
    "gidNumber": 500573,
    "parents": [],
    "users": null
  },
  "secondaryGroups": [],
  "userStatus": "ACTIVE",
  "externalId": "hdf_61230996-664f-4422-9caa-76cf086f0d6c@unity-hdf"
}Group Management:In all shortness:Gibt rudimentäre Infos über die Gruppe aus:https://bwidm-test.scc.kit.edu/rest/group-admin/find/id/<id>
https://bwidm-test.scc.kit.edu/rest/group-admin/find/name/<name>Gibt genauere Infos raus. Z.B. auch die Member und übergeordnete Gruppen:https://bwidm-test.scc.kit.edu/rest/group-admin/find-detail/id/<id>
https://bwidm-test.scc.kit.edu/rest/group-admin/find-detail/name/<name>Legt eine Gruppe an:https://bwidm-test.scc.kit.edu/rest/group-admin/create/<ssn>/<name>- Der Service Short Name, des Dienstes, dem die Gruppe zugeordnet ist.Fügt ein Benutzer einer Gruppe dazu, oder nimmt ihn raus:https://bwidm-test.scc.kit.edu/rest/group-admin/add/groupId/<groupId>/userId/<userId>
https://bwidm-test.scc.kit.edu/rest/group-admin/add/groupId/<groupId>/userId/<userId>- Datenbank Id des Benutzers
 - Datenbank Id der GruppeLDAP ConfigurationBindDN: uid=fileservice-read,ou=admin,ou=login-test,dc=bwidm-test,dc=de
BindPW: $PASS
Base: ou=login-test,dc=bwidm-test,dc=deFeudal systemd serviceTo enable a feudal service this might be helpful:systemctl --user --now enable feudalClient@0