Added some Okta work. This lets Ansible become the source of truth soon. Need to work the api module to exact search rather then a fuzzy search. Started to get back into docker to maintain homelab.

This commit is contained in:
James Tombleson 2019-10-23 15:54:32 -07:00
parent 2081ea949b
commit c95f1099a0
20 changed files with 1155 additions and 61 deletions

8
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"cSpell.ignoreWords": [
"ansible",
"okta",
"specialcounsel",
"vault"
]
}

View File

@ -11,8 +11,11 @@
# some basic default values...
inventory = ./hosts
library = /usr/share/my_modules/
inventory = ./inventory/
#library = /usr/share/my_modules/:./modules/
# Looks like modules can only be pointed to a single directory
library = ./modules/
module_utils = /usr/share/my_module_utils/
remote_tmp = ~/.ansible/tmp
local_tmp = ~/.ansible/tmp
@ -255,7 +258,7 @@ vault_password_file = ./.ansible_vault
# You can enable this feature by setting retry_files_enabled to True
# and you can change the location of the files by setting retry_files_save_path
#retry_files_enabled = False
retry_files_enabled = False
#retry_files_save_path = ~/.ansible-retry
# squash actions

46
dev.yml
View File

@ -1,46 +0,0 @@
---
all:
hosts:
dmi-dev01:
children:
linux:
hosts:
172.20.0.142:
vars:
ansible_user: ansible
ansible_connection: ssh
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
33353561613531336536313335356236643530346538373638653330306636386435633965336136
3464366635373661383466333464663238663565343839310a376666386237313566386235633739
66323434636365303335326133396137393031396531313533326263363066636237313139353538
6134616232336365610a363033343639616563316330363966326330646162613034633532366230
3439
ansible_become_method: sudo
ansible_become_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
33353561613531336536313335356236643530346538373638653330306636386435633965336136
3464366635373661383466333464663238663565343839310a376666386237313566386235633739
66323434636365303335326133396137393031396531313533326263363066636237313139353538
6134616232336365610a363033343639616563316330363966326330646162613034633532366230
3439
ansible_python_interpreter: /usr/bin/python3
windows:
hosts:
dmi-dev01:
vars:
ansible_user: svcansible
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
33353561613531336536313335356236643530346538373638653330306636386435633965336136
3464366635373661383466333464663238663565343839310a376666386237313566386235633739
66323434636365303335326133396137393031396531313533326263363066636237313139353538
6134616232336365610a363033343639616563316330363966326330646162613034633532366230
3439
ansible_connection: winrm
ansible_port: 5985
ansible_winrm_scheme: http
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore

32
inventory/home.yaml Normal file
View File

@ -0,0 +1,32 @@
---
all:
hosts:
children:
linux:
192.160.0.60
vars:
ansible_user: !vault |
$ANSIBLE_VAULT;1.1;AES256
33393963653363383638373235363531386238626138366632336531663437373634333766656437
3462613266323931343431616465623439626534646238640a616461633434626631376266383234
61386535373738386632626331353665643137373234323566326633386234666534616330306639
3739633437353337380a373437643563663163653834653637363861663639363635333866613435
6636
ansible_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62386164373234666130346666653866663136623261386364636632303430616135343132303631
3632316465666237613232313761353135316433376562360a633931646238326139336532373633
32666636326332346536366165373030346265626633646335303033636337333336323164636338
3036393466633634640a313262373661623731623639343565653061663830303537666136346165
3834
ansible_connection: ssh
ansible_become_method: sudo
ansible_become_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
62386164373234666130346666653866663136623261386364636632303430616135343132303631
3632316465666237613232313761353135316433376562360a633931646238326139336532373633
32666636326332346536366165373030346265626633646335303033636337333336323164636338
3036393466633634640a313262373661623731623639343565653061663830303537666136346165
3834
ansible_python_interpreter: /usr/bin/python3

317
modules/okta_groups.py Normal file
View File

@ -0,0 +1,317 @@
#!/usr/bin/python
# (c) 2019, Whitney Champion <whitney.ellis.champion@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = """
module: okta_groups
short_description: Communicate with the Okta API to manage groups
description:
- The Okta groups module manages Okta groups
version_added: "1.0"
author: "Whitney Champion (@shortstack)"
options:
organization:
description:
- Okta subdomain for your organization. (i.e.
mycompany.okta.com).
required: false
default: None
api_key:
description:
- Okta API key.
required: false
default: None
action:
description:
- Action to take against groups API.
required: false
default: list
choices: [ create, update, delete, list, add_user, remove_user ]
id:
description:
- ID of the group.
required: false
default: None
name:
description:
- Group name.
required: false
default: None
description:
description:
- Group description.
required: false
default: yes
limit:
description:
- List limit.
required: false
default: 200
user_id:
description:
- ID of user to add to group.
required: false
default: None
"""
EXAMPLES = '''
# List groups
- okta_groups:
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
limit: 200
# Create group
- okta_groups:
action: create
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
name: "Imaginary Creatures"
description: "They are so majestic"
# Update group
- okta_groups:
action: update
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM457"
name: "Imaginary Creatures"
description: "They are so majestic and beautiful"
# Add user to group
- okta_groups:
action: add_user
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM457"
user_id: "01c5pEucucMPWXjFM456"
# Remove user from group
- okta_groups:
action: remove_user
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM457"
user_id: "01c5pEucucMPWXjFM456"
# Delete group
- okta_groups:
action: delete
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM457"
'''
RETURN = r'''
json:
description: The JSON response from the Okta API
returned: always
type: complex
msg:
description: The HTTP message from the request
returned: always
type: str
sample: OK (unknown bytes)
status:
description: The HTTP status code from the request
returned: always
type: int
sample: 200
url:
description: The actual URL used for the request
returned: always
type: str
sample: https://www.ansible.com/
'''
def create(module,base_url,api_key,name,description):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
payload = {}
profile = {}
if name is not None:
profile['name'] = name
if description is not None:
profile['description'] = description
payload['profile'] = profile
url = base_url
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='POST', data=module.jsonify(payload))
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def update(module,base_url,api_key,id,name,description):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
payload = {}
profile = {}
if name is not None:
profile['name'] = name
if description is not None:
profile['description'] = description
payload['profile'] = profile
url = base_url+"/%s" % (id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='PUT', data=module.jsonify(payload))
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def delete(module,base_url,api_key,id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s" % (id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='DELETE') # delete
if info['status'] != 204:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def list(module,base_url,api_key,limit):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/?limit=%s" % (limit)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='GET')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def add_user(module,base_url,api_key,id,user_id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s/users/%s" % (id,user_id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='PUT')
if info['status'] != 204:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def remove_user(module,base_url,api_key,id,user_id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s/users/%s" % (id,user_id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='DELETE')
if info['status'] != 204:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def main():
module = AnsibleModule(
argument_spec = dict(
organization = dict(type='str', default=None),
api_key = dict(type='str', no_log=True),
action = dict(type='str', default='list', choices=['create', 'update', 'delete', 'list', 'add_user', 'remove_user']),
id = dict(type='str', default=None),
user_id = dict(type='str', default=None),
name = dict(type='str', default=None),
description = dict(type='str', default=None),
limit = dict(type='int', default=200)
)
)
organization = module.params['organization']
api_key = module.params['api_key']
action = module.params['action']
id = module.params['id']
user_id = module.params['user_id']
name = module.params['name']
description = module.params['description']
limit = module.params['limit']
base_url = "https://%s-admin.okta.com/api/v1/groups" % (organization)
if action == "create":
status, message, content, url = create(module,base_url,api_key,name,description)
elif action == "update":
status, message, content, url = update(module,base_url,api_key,id,name,description)
elif action == "delete":
status, message, content, url = delete(module,base_url,api_key,id)
elif action == "list":
status, message, content, url = list(module,base_url,api_key,limit)
elif action == "add_user":
status, message, content, url = add_user(module,base_url,api_key,id,user_id)
elif action == "remove_user":
status, message, content, url = remove_user(module,base_url,api_key,id,user_id)
uresp = {}
content = to_text(content, encoding='UTF-8')
try:
js = json.loads(content)
except ValueError, e:
js = ""
uresp['json'] = js
uresp['status'] = status
uresp['msg'] = message
uresp['url'] = url
module.exit_json(**uresp)
# import module snippets
import json
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
if __name__ == '__main__':
main()

455
modules/okta_users.py Normal file
View File

@ -0,0 +1,455 @@
#!/usr/bin/python
# (c) 2019, Whitney Champion <whitney.ellis.champion@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = """
module: okta_users
short_description: Communicate with the Okta API to manage users
description:
- The Okta user module manages Okta users
version_added: "1.0"
author: "Whitney Champion (@shortstack)"
options:
organization:
description:
- Okta subdomain for your organization. (i.e.
mycompany.okta.com).
required: false
default: None
api_key:
description:
- Okta API key.
required: false
default: None
action:
description:
- Action to take against user API.
required: false
default: list
choices: [ create, update, delete, list, activate, deactivate ]
id:
description:
- ID of the user.
required: false
default: None
login:
description:
- Username.
required: false
default: None
activate:
description:
- Whether or not the new user is activate.
required: false
default: yes
password:
description:
- Password.
required: false
default: None
first_name:
description:
- First name.
required: false
default: None
last_name:
description:
- Last name.
required: false
default: None
email:
description:
- Email.
required: false
default: None
group_ids:
description:
- List of Group IDs to add the user to.
required: false
default: None
limit:
description:
- List limit.
required: false
default: 25
"""
EXAMPLES = '''
# List users
- okta_users:
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
limit: 25
# Create user
- okta_users:
action: create
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
login: "whitney@unicorns.lol"
first_name: "Whitney"
last_name: "Champion"
email: "whitney@unicorns.lol"
password: "cookiesaredelicious"
activate: yes
# Create user in group(s)
- okta_users:
action: create
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
login: "whitney@unicorns.lol"
first_name: "Whitney"
last_name: "Champion"
email: "whitney@unicorns.lol"
password: "cookiesaredelicious"
group_ids:
- "00f5b3gqiLpE114tV2M7"
activate: yes
# Create multiple users in group
- okta_users:
action: create
organization: "crypto"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
login: "{{ item.login }}"
first_name: "{{ item.first_name }}"
last_name: "{{ item.last_name }}"
email: "{{ item.email }}"
password: "{{ item.password }}"
group_ids:
- "00f5b3gqiLpE324tV2M7"
activate: "{{ item.activate }}"
with_items:
- { login: "alice@aol.com", first_name: "Alice", last_name: "A", email: "alice@aolcom", password: "ilovebob111", activate: yes }
- { login: "bob@aol.com", first_name: "Bob", last_name: "B", email: "bob@aolcom", password: "ilovealice111", activate: yes }
# Update user's email address
- okta_users:
action: update
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM456"
email: "whitney@ihateunicorns.lol"
# Activate user
- okta_users:
action: activate
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM456"
# Deactivate user
- okta_users:
action: deactivate
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM456"
# Delete user
- okta_users:
action: delete
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM456"
# Get a list of groups a user is in
- okta_users:
action: usergroups
organization: "unicorns"
api_key: "TmHvH4LY9HH9MDRDiLChLGwhRjHsarTCBzpwbua3ntnQ"
id: "01c5pEucucMPWXjFM456"
'''
RETURN = r'''
json:
description: The JSON response from the Okta API
returned: always
type: complex
msg:
description: The HTTP message from the request
returned: always
type: str
sample: OK (unknown bytes)
status:
description: The HTTP status code from the request
returned: always
type: int
sample: 200
url:
description: The actual URL used for the request
returned: always
type: str
sample: https://www.ansible.com/
'''
def create(module,base_url,api_key,login,password_input,email,first_name,last_name,group_ids,activate):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
payload = {}
profile = {}
credentials = {}
password = {}
groupIds= []
if first_name is not None:
profile['firstName'] = first_name
if last_name is not None:
profile['lastName'] = last_name
if email is not None:
profile['email'] = email
if login is not None:
profile['login'] = login
if password_input is not None:
password['value'] = password_input
if group_ids is not None:
groupIds = group_ids
credentials['password'] = password
payload['credentials'] = credentials
payload['groupIds'] = groupIds
payload['profile'] = profile
url = base_url+"?activate=%s" % (activate)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='POST', data=module.jsonify(payload))
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def update(module,base_url,api_key,id,login,email,first_name,last_name):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s" % (id)
payload = {}
profile = {}
if first_name is not None:
profile['firstName'] = first_name
if last_name is not None:
profile['lastName'] = last_name
if email is not None:
profile['email'] = email
if login is not None:
profile['login'] = login
payload['profile'] = profile
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='POST', data=module.jsonify(payload))
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def delete(module,base_url,api_key,id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s" % (id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='DELETE')
if info['status'] != 204:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def activate(module,base_url,api_key,id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s/lifecycle/activate" % (id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='POST')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def deactivate(module,base_url,api_key,id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s/lifecycle/deactivate" % (id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='POST')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def list(module,base_url,api_key,limit):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/?limit=%s" % (limit)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='GET')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def findByLogin(module, base_url, api_key, login):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
#url = base_url+"?q=%s&limit=1" % (login)
url = base_url+"?filter=profile.login+eq+\"%s\"" % (login)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='GET')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def findByName(module, base_url, api_key, Name):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"?q=%s&limit=1" % (Name)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='GET')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def getusergroups(module, base_url, api_key, id):
headers = '{ "Content-Type": "application/json", "Authorization": "SSWS %s", "Accept": "application/json" }' % (api_key)
url = base_url+"/%s/groups" % (id)
response, info = fetch_url(module=module, url=url, headers=json.loads(headers), method='GET')
if info['status'] != 200:
module.fail_json(msg="Fail: %s" % ( "Status: "+str(info['msg']) + ", Message: " + str(info['body'])))
try:
content = response.read()
except AttributeError:
content = info.pop('body', '')
return info['status'], info['msg'], content, url
def main():
module = AnsibleModule(
argument_spec = dict(
organization = dict(type='str', default=None),
api_key = dict(type='str', no_log=True),
action = dict(type='str', default='list', choices=['create', 'update', 'delete', 'list', 'activate', 'deactivate', 'usergroups']),
id = dict(type='str', default=None),
login = dict(type='str', default=None),
password = dict(type='str', default=None, no_log=True),
first_name = dict(type='str', default=None),
last_name = dict(type='str', default=None),
email = dict(type='str', default=None),
group_ids = dict(type='list', default=None),
limit = dict(type='int', default=25),
activate = dict(type='bool', default='yes')
)
)
organization = module.params['organization']
api_key = module.params['api_key']
action = module.params['action']
id = module.params['id']
login = module.params['login']
password = module.params['password']
first_name = module.params['first_name']
last_name = module.params['last_name']
email = module.params['email']
group_ids = module.params['group_ids']
limit = module.params['limit']
activate = module.params['activate']
base_url = "https://%s-admin.okta.com/api/v1/users" % (organization)
if action == "create":
status, message, content, url = create(module,base_url,api_key,login,password,email,first_name,last_name,group_ids,activate)
elif action == "update":
status, message, content, url = update(module,base_url,api_key,id,login,email,first_name,last_name)
elif action == "delete":
status, message, content, url = deactivate(module,base_url,api_key,id)
status, message, content, url = delete(module,base_url,api_key,id)
elif action == "activate":
status, message, content, url = activate(module,base_url,api_key,id)
elif action == "deactivate":
status, message, content, url = deactivate(module,base_url,api_key,id)
elif action == "list":
if login is not None:
status, message, content, url = findByLogin(module,base_url,api_key,login)
elif first_name is not None:
status, message, content, url = findByName(module,base_url,api_key, first_name)
elif last_name is not None:
status, message, content, url = findByName(module,base_url,api_key,last_name)
else:
status, message, content, url = list(module,base_url,api_key,limit)
elif action == "usergroups":
status, message, content, url = getusergroups(module, base_url, api_key, id)
uresp = {}
content = to_text(content, encoding='UTF-8')
try:
js = json.loads(content)
except ValueError, e:
js = ""
uresp['json'] = js
uresp['status'] = status
uresp['msg'] = message
uresp['url'] = url
module.exit_json(**uresp)
# import module snippets
import json
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
if __name__ == '__main__':
main()

View File

@ -0,0 +1,47 @@
---
# https://github.com/linuxserver/docker-hydra2
- name: Media Server
hosts: localhost
vars_files:
- vars.yml
tasks:
- name: pip docker
pip:
name: docker
- name: Hydra Config
docker_volume:
name: "{{ hydra_config }}"
state: present
- name: Volume Shared Downloads
docker_volume:
name: "{{ shared_downloads }}"
state: present
- name: Hydra Network
docker_network:
name: "{{ network }}"
- name: stop hydra
docker_container:
name: hydra
state: stopped
- name: Make Hydra
docker_container:
name: hydra
image: linuxserver/hydra2
state: started
env:
PUID=1000
PGID=1000
TZ=Europe/London
ports:
- 5076:5076
volumes:
- "{{ hydra_config }}:/config"
- "{{ shared_downloads }}:/downloads"
networks:
- name: "{{ network }}"

View File

@ -0,0 +1,12 @@
---
# Volumes
sonarr_data: sonarr_data
sonarr_config: sonarr_config
osx_sonarr_data: ~/doc
hydra_config: hydra_config
shared_downloads: media_downloads
# Networks
network: net_hydra

View File

@ -1,12 +0,0 @@
- name: Deploy OwnCloud
hosts: linux
become_method: sudo
tasks:
- name: Check if docker is installed.
apt:
name: docker
state: present

View File

@ -0,0 +1,41 @@
---
- name: maintain okta users
hosts: localhost
vars_files:
- okta_vars.yml
vars:
first_name: API
last_name: Test
email: "{{ email_deleteme }}"
login: "{{ email_deleteme }}"
isActive: True
tasks:
- name: Check for {{ login }}
okta_users:
organization: "{{ org }}"
api_key: "{{ api }}"
action: list
login: "{{ login }}"
register: oktalist
- name: debug
debug:
msg: "{{ oktalist }}"
# if the account is not found, make it
#- name: Create {{ login }}
# okta_users:
## organization: "{{ organization }}"
# api_key: "{{ api_key }}"
# action: create
# login: "{{ login }}"
# email: "{{ email }}"
# first_name: "{{ first_name }}"
# last_name: "{{ last_name }}"
# when:
# - oktalist['json'] is not defined
# - isActive|bool == True

View File

@ -0,0 +1,18 @@
---
- name: Debug Okta Groups
hosts: localhost
vars_files: okta_vars.yml
tasks:
- name: Get Okta Group
okta_groups:
organization: "{{ org }}"
api_key: "{{ api }}"
action: list
limit: 200
register: res
- name: show res
debug:
msg: "{{ item.profile.name }} {{ item.id }}"
loop: "{{ res.json }}"

View File

@ -0,0 +1,32 @@
- name: Show okta_users result
hosts: localhost
vars_files: okta_vars.yml
#include_vars: okta_vars.yml
tasks:
- name: list 1
okta_users:
organization: "{{ org }}"
api_key: "{{ api }}"
action: list
email: "{{ email_deleteme }}"
#limit: 1
register: res
- name: display result
debug:
msg: "{{ res.json }}"
- name: user groups
okta_users:
organization: "{{ org }}"
api_key: "{{ api }}"
action: usergroups
id: "{{ res.json.0.id }}"
register: grps
- name: display groups
debug:
msg: "{{ grps }}"

View File

@ -0,0 +1,13 @@
---
- name: Group Test
hosts: localhost
vars_files: okta_vars.yml
tasks:
- name: add group
okta_groups:
organization: "{{ org }}"
api_key: "{{ api }}"
action: add_user
id: "00g1jfcegwGw1Lsuh357"
user_id: 00u1kekdg8ewrmdmt357

View File

@ -0,0 +1,39 @@
- name: maintain okta users
hosts: localhost
vars_files:
- okta_vars.yml
tasks:
- name: manage delete.me
include_role:
name: luther38.okta
vars:
organization: "{{ org }}"
api_key: "{{ api }}"
first_name: API
last_name: Test
email: "{{ email_deleteme }}"
login: "{{ email_deleteme }}"
isActive: True
add_groups:
#- 00g1jfcegwGw1Lsuh357
remove_groups:
- 00g1jfcegwGw1Lsuh357
- name: delete me2
include_role:
name: luther38.okta
vars:
organization: "{{ org }}"
api_key: "{{ api }}"
first_name: API
last_name: Test2
email: "{{ email_deleteme2 }}"
login: "{{ email_deleteme2 }}"
isActive: True
add_groups:
#- 00g1jfcegwGw1Lsuh357
remove_groups:
- 00g1jfcegwGw1Lsuh357

View File

@ -0,0 +1,25 @@
org: specialcounsel
api: !vault |
$ANSIBLE_VAULT;1.1;AES256
38653364346561346262373864383039383062363465656531393561313162313764363230616461
3861383930646331366132626132346430313238366439320a363636363938363431646631316362
30663937343631353430326161616331373539343064613663393862653364643838623335303639
6561326532373939630a633134323530303632653733663039323238363961373832386638666535
61646234656263643439613135303934323264303235313737656238366462633365333762646162
6461376235383531643464396638323162373364373433353934
email_deleteme: !vault |
$ANSIBLE_VAULT;1.1;AES256
61326435326361386537303861313332643434316433643737356434333836346435626361396539
6536373565343363366433343931643363653465636264320a363466646337633138663134666263
64613133383336653132366663393734343135633932323731326164653137323936366432613765
3737653131353635370a656339366330373761326135653739313731613230383561306431646165
36656339616330393539336563343663303638626337336564306234376161383634
email_demeteme2: !vault |
$ANSIBLE_VAULT;1.1;AES256
39646663353734646332613430656433356265623235383931636334653463393030653733653963
6638326232613733613462363133663833323532653939620a646239303535626462636331616562
36353836393333333664386131376139323662336538373435653939626565363837356234306531
6539386434623366320a303438643832353732393833353434363662326635666430613333636431
61366265643632363939666534613138623262626230613739373833363538383030

View File

@ -0,0 +1,7 @@
# localhost
The playbooks found here are not working against another host to maintain the configuration. They only need the ansible host that contains the playbook and some modules.
## Okta
These playbooks work with Okta's REST API so you do not need to jump into another server.

View File

@ -48,6 +48,7 @@
#TODO The job seems to stop here for some reason
- name: remove cask - dotnet-sdk
become: true
homebrew_cask:
name: dotnet-sdk
state: absent

View File

@ -0,0 +1,12 @@
---
organization: ''
api_key: ''
first_name: ''
last_name: ''
email: ''
login: ''
status: ''
add_groups:
remove_groups:

View File

@ -0,0 +1,90 @@
---
- name: Check for {{ login }}
okta_users:
organization: "{{ organization }}"
api_key: "{{ api_key }}"
action: list
login: "{{ login }}"
register: oktalist
# if the account is not found, make it
- name: Create {{ login }}
okta_users:
organization: "{{ organization }}"
api_key: "{{ api_key }}"
action: create
login: "{{ login }}"
email: "{{ email }}"
first_name: "{{ first_name }}"
last_name: "{{ last_name }}"
when:
- oktalist['json'] is not defined
- isActive|bool == True
- name: Update {{ login }} first_name
okta_users:
organization: "{{ organization }}"
api_key: "{{ api_key }}"
action: update
id: "{{ oktalist.json.0.id }}"
first_name: "{{ first_name }}"
when:
- oktalist.json.0.profile.firstName != first_name
- isActive|bool == True
- name: Update {{ login }} last_name
okta_users:
organization: "{{ organization }}"
api_key: "{{ api_key }}"
action: update
id: "{{ oktalist.json.0.id }}"
last_name: "{{ last_name }}"
when:
- oktalist.json.0.profile.lastName != last_name
- isActive|bool == True
- name: Update {{ login }} email
okta_users:
organization: "{{ organization }}"
api_key: "{{ api_key }}"
action: update
id: "{{ oktalist.json.0.id }}"
email: "{{ email }}"
when:
- oktalist.json.0.profile.email != email
- isActive|bool == True
- name: Disable {{ login }}
okta_users:
organization: "{{ organization }}"
api_key: "{{ api_key }}"
action: deactivate
id: "{{ oktalist.json.0.id }}"
when:
- oktalist.json is defined
- isActive|bool == False
- name: debug
debug:
msg: "{{ item }}"
with_items: "{{ add_groups }}"
- name: add groups
okta_groups:
action: add_user
organization: "{{ organization }}"
api_key: "{{ api_key }}"
user_id: "{{ oktalist.json.0.id }}"
id: "{{ item }}"
with_items: "{{ add_groups }}"
ignore_errors: yes
- name: remove groups
okta_groups:
action: remove_user
organization: "{{ organization }}"
api_key: "{{ api_key }}"
user_id: "{{ oktalist.json.0.id }}"
id: "{{ item }}"
with_items: "{{ remove_groups }}"
ignore_errors: yes