-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use lemonldap api to edit the configuration #8
Labels
enhancement
New feature or request
Comments
Hello, it is a good idea. We already tried this for W'Sweet, but code is not yet published. |
ok, could you share this code ? I would like those features (it could be easier than writing them from scratch) |
Here is an ansible module written by @maxbes to create OIDC RP through API: #!/usr/bin/python
# Copyright: (c) 2018, Terry Jones <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
---
module: lemonldap_oidc_rp
short_description: This module creates a new OIDC Relying Party in LemonLDAP
version_added: "2.8"
description:
- "This module uses the Manager API to create a new OIDC Relying Party"
options:
name:
description:
- The arbitrary, internal name of this party in LemonLDAP::NG
required: true
state:
description:
- Whether the party should exist or not, taking action if the state is different from what is stated
type: str
choices: [ absent, present ]
default: present
options:
description:
- Dictionnary of OIDC Relying Party options
type: dict
clientId=dict(type='str', required=False),
clientId:
description:
- The OpenID Connect Client ID of this party
redirectUris:
description:
- The list of allowed redirect URIs for this party
type: list
exported_variables:
description:
- Dictionnary of LemonLDAP::NG session attributes to send to this party
- The key of each dictionnary is the name of the OIDC claim
- The value is the name of LemonLDAP session attribute to use for this claim
type: dict
extra_claims:
description:
- Dictionary of additional scopes you want this party to support
- The key of each dictionnary is the name of a scope
- The value is the space-separated list of OIDC claims released by this scope
type: dict
api_url:
description:
- URL of the LemonLDAP::NG Manager API
type: str
required: true
url_username:
description:
- Username to login on the Manager API as
type: str
url_password:
description:
- Password for the Manager API
type: str
timeout:
description:
- Request timeout for the Manager API
type: int
default: 60
author:
- Your Name (@yourhandle)
'''
EXAMPLE = '''
# Create a new OIDC Relying party
- name: create
lemonldap_oidc_rp:
api_url: https://manager-api.dev.wsweet.cloud/
url_username: manager
url_password: password
name: myopenidapp
state: present
clientId: myclientid
options:
clientSecret: myclientsecret
redirectUris:
- https://myapp.dev.wsweet.cloud/oauth2/callback
exported_variables:
email: mail
family_name: sn
given_name: givenName
preferred_username: uid
'''
RETURN = '''
original_message:
description: The original name param that was passed in
type: str
returned: always
message:
description: The output message that the test module generates
type: str
returned: always
'''
import json
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url
from ansible.module_utils.lemonldap_api import LemonApi,lemon_base_spec
class OidcRpApi(LemonApi):
def get_object(self):
name = self.module.params['name']
url = "/providers/oidc/rp/{0}".format(name)
return self.api_request(url)
def differs(self, current_object):
if self.module.params['clientId'] != current_object['clientId']:
return True
if self._differs_hash(current_object, 'options', 'options'):
return True
if self._differs_hash(current_object, 'exported_variables', 'exportedVars'):
return True
if self._differs_hash(current_object, 'extra_claims', 'extraClaims'):
return True
return False
def _differs_hash(self, current_object, option_name, payload_key):
specification = self.module.params[option_name]
state = current_object[payload_key]
if specification is None:
return False
for keyname in specification.keys():
if not keyname in state or specification[keyname] != state[keyname]:
return True
def build_payload(self,confKey = None):
data = {}
if not confKey is None:
data['confKey'] = confKey
if 'clientId' in self.module.params:
data['clientId'] = self.module.params['clientId']
if 'redirectUris' in self.module.params:
data['redirectUris'] = self.module.params['redirectUris']
if 'options' in self.module.params:
data['options'] = self.module.params['options']
if 'exported_variables' in self.module.params:
data['exportedVars'] = self.module.params['exported_variables']
if 'extra_claims' in self.module.params:
data['extraClaims'] = self.module.params['extra_claims']
return data
def create(self):
url = "/providers/oidc/rp"
data = self.build_payload(self.module.params['name'])
self.api_request(url, method='POST', data=data, expect=201)
self.module.exit_json(changed=True)
def update(self):
url = "/providers/oidc/rp/{0}".format(self.module.params['name'])
data = self.build_payload()
self.api_request(url, method='PATCH', data=data, expect=204)
self.module.exit_json(changed=True)
def delete(self):
url = "/providers/oidc/rp/{0}".format(self.module.params['name'])
self.api_request(url, method='DELETE', expect=204)
self.module.exit_json(changed=True)
def run_module():
# define available arguments/parameters a user can pass to the module
module_args = lemon_base_spec(dict(
name=dict(type='str', required=True),
clientId=dict(type='str', required=False),
redirectUris=dict(type='list', elements='str', required=False,),
options=dict(type='dict', required=False,),
exported_variables=dict(type='dict', required=False,),
extra_claims=dict(type='dict', required=False,),
state=dict(type='str', default="present", choices=["present", "absent"]),
))
# seed the result dict in the object
# we primarily care about changed and state
# change is if this module effectively modified the target
# state will include any data that you want your module to pass back
# for consumption, for example, in a subsequent task
result = dict(
changed=False,
)
# the AnsibleModule object will be our abstraction working with Ansible
# this includes instantiation, a couple of common attr would be the
# args/params passed to the execution, as well as if the module
# supports check mode
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
api = OidcRpApi(module)
api.run()
def main():
run_module()
if __name__ == '__main__':
main() |
great thx for sharing this piece of code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
It could be nice to be able to adapt the config of a running LemonLDAP through the API within ansible. I know there is an API for the manager, but don't know if we have enough features there to create an Ansible module for this purpose. What do you think ? It could be fun to explore and create a first PoC with some very simple object (menucat or menuapp). If you think that's good idea, i will spend some time the few next weeks exploring this.
Best regards,
l.
The text was updated successfully, but these errors were encountered: