diff --git a/action_plugins/synology_dsm_api_request.py b/action_plugins/synology_dsm_api_request.py index 87ca501..f44b7b5 100644 --- a/action_plugins/synology_dsm_api_request.py +++ b/action_plugins/synology_dsm_api_request.py @@ -5,10 +5,10 @@ __metaclass__ = type import urllib +import json from ansible.plugins.action import ActionBase - class ActionModule(ActionBase): TRANSFERS_FILES = True @@ -16,69 +16,129 @@ class ActionModule(ActionBase): PARAM_DEFAULTS = dict( base_url = 'http://localhost:5000', request_method = 'GET', - login_cookie = None, - login_user = None, + login_cookie = None, + login_user = None, login_password = None, cgi_path = '/webapi/', cgi_name = 'entry.cgi', - api_name = None, + api_name = None, api_version = '1', - api_method = None, - api_params = None, + api_method = None, + api_params = None, request_json = None, ) - def run(self, tmp=None, task_vars=None): - self._supports_async = True - - if task_vars is None: - task_vars = dict() - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect + def extract_params(self): + """return the params with none items removed + :return: a dictionary of the params, no Nones, and correctly prioritized to the user input + """ - # Build task args + # Capture the default params task_args = self.PARAM_DEFAULTS.copy() + + # Undo the json -> python-literal auto-transformation made by jinja2 + # follow https://github.com/ansible/ansible/issues/68643#issue-592816310 + if ("api_params") in self._task.args: + if ("compound") in self._task.args["api_params"]: + compound = self._task.args["api_params"]["compound"] + if (isinstance(compound, dict) or type(compound) == list): + json_str = json.dumps(compound) + self._task.args["api_params"]["compound"] = json_str + else: + # mostly an AnsibleUnicode type + # and jinja template didn't touch it + pass + + # Overwrite the params with the input args task_args.update(self._task.args) + # Remove the none items for arg in task_args.keys(): - if task_args[arg] is None: - del task_args[arg] - - # Build 'uri' module params + if task_args[arg] is not None: + print("{}:\t {}".format(arg, type(task_args[arg]))) + return {k: v for k, v in task_args.items() if v is not None} + + def build_uri(task_args): + """ Create base_url/cgi_path/cgi_name and set the GET or POST method + + :param dict task_args: the arguments of the request, including the url, path, method, ... etc. + :return: A uri representing the request, ie: http://localhost:5000/webapi/entry.cgi + It will include the username and password, at least for the first time + before having the login_cookie + """ uri_params = dict( url = "%s/%s/%s" % (task_args['base_url'], task_args['cgi_path'].strip('/'), task_args['cgi_name']), method = task_args['request_method'], ) + if 'login_cookie' in task_args: uri_params['headers'] = dict(Cookie = task_args['login_cookie']) + if task_args['request_method'] == 'POST': if 'request_json' in task_args: + # fill json body uri_params['body'] = task_args['request_json'] uri_params['body_format'] = 'json' else: + # fill form-urlencoded body tmp_body = dict( - api = task_args['api_name'], + api = task_args['api_name'], version = task_args['api_version'], - method = task_args['api_method'], + method = task_args['api_method'], ) + if 'api_params' in task_args: tmp_body.update(task_args['api_params']) + uri_params['body'] = tmp_body uri_params['body_format'] = 'form-urlencoded' + elif task_args['request_method'] == 'GET': - uri_params['url'] += '?api=%s&version=%s&method=%s' % (task_args['api_name'], task_args['api_version'], task_args['api_method']) + uri_params['url'] += '?api=%s&version=%s&method=%s' %( + task_args['api_name'], + task_args['api_version'], + task_args['api_method'] + ) + + # encode further API params into the URL + # ie: include the username and password for the login if 'api_params' in task_args: try: uri_params['url'] += '&%s' % urllib.parse.urlencode(task_args['api_params']) except AttributeError: uri_params['url'] += '&%s' % urllib.urlencode(task_args['api_params']) - result = self._execute_module('uri', module_args=uri_params, task_vars=task_vars, wrap_async=self._task.async_val) + return uri_params + + def is_request_failing(result): + return (result.get('failed', False) or + result.get('json', {}).get('success', None) == False or + result.get('json', {}).get('data', {}).get('has_fail', None) == True + ) + + def run(self, tmp=None, task_vars=None): + self._supports_async = True + + if task_vars is None: + task_vars = dict() + + result = super(ActionModule, self).run(tmp, task_vars) + del tmp # tmp no longer has any effect + + # Build task args + task_args = self.extract_params() + + # Build URI compliant with synology API + uri_params = ActionModule.build_uri(task_args) + + result = self._execute_module('uri', + module_args=uri_params, + task_vars=task_vars, + wrap_async=self._task.async_val) if not self._task.async_val: self._remove_tmp_path(self._connection._shell.tmpdir) - if result.get('failed', False) or (result.get('json', {}).get('success', None) == False): + if ActionModule.is_request_failing(result): result['failed'] = True return result diff --git a/defaults/main/login.yml b/defaults/main/login.yml new file mode 100644 index 0000000..5de4c86 --- /dev/null +++ b/defaults/main/login.yml @@ -0,0 +1,7 @@ +--- +synology_dsm_login_user: admin_devops_user +synology_dsm_login_pass: dXNlX2Ffc3Ryb25nX3Bhc3N3b3JkX2xpa2VfdGhpcw== + +# NOTE: for passwords, use a base64 hash, in example: +# ```echo -n use_a_strong_password_like_this | base64``` + diff --git a/defaults/main.yml b/defaults/main/main.yml similarity index 58% rename from defaults/main.yml rename to defaults/main/main.yml index 1cfa7d8..5b549b8 100644 --- a/defaults/main.yml +++ b/defaults/main/main.yml @@ -1,12 +1,16 @@ --- -synology_dsm_host: '{{ inventory_hostname }}' -synology_dsm_base_url: http://{{ synology_dsm_host }}:5000 +# Only overwrite when the user supplied below will get it's password changed! +# as it's password will be exposed while communicating to this URI +# Overwriting is only useful if the ssh configuration or the very initial configs +# will be managed through this script, +# however it's advisable that the consecutive steps be executed through 127.0.0.1 +# with an ssh tunnel utilized +synology_dsm_host: 127.0.0.1 +synology_dsm_port: 5000 +synology_dsm_base_url: http://{{synology_dsm_host}}:{{synology_dsm_port}} synology_dsm_base_path: webapi synology_dsm_cgi_name: entry.cgi -synology_dsm_username: admin -synology_dsm_password: changeme - synology_dsm_ssh_enable: true synology_dsm_ssh_port: 22 synology_dsm_telnet_enable: false diff --git a/defaults/main/notif_mail.yml b/defaults/main/notif_mail.yml new file mode 100644 index 0000000..ffc8e70 --- /dev/null +++ b/defaults/main/notif_mail.yml @@ -0,0 +1,13 @@ +synology_dsm_notif_mail_enable: true +synology_dsm_notif_mail_receipent: receiver@example.com +synology_dsm_notif_mail_prefix: "[SYNO_EMAIL_PREFIX]" +synology_dsm_notif_mail_server: smtp.gmail.com +synology_dsm_notif_mail_port: 587 +synology_dsm_notif_mail_ssl: true +synology_dsm_notif_mail_oauth: false +synology_dsm_notif_mail_welcome_mail: false +synology_dsm_notif_mail_auth_enable: true +synology_dsm_notif_mail_auth_user: sender@gmailInThisCase.com +synology_dsm_notif_mail_auth_pass: YV9zdHJvbmdfcGFzc3dvcmRfbGlrZV90aGlz +synology_dsm_notif_mail_sender_name: Sender Name +synology_dsm_notif_mail_sender_mail: sender@gmailInThisCase.com diff --git a/defaults/main/user_create.yml b/defaults/main/user_create.yml new file mode 100644 index 0000000..1b2344a --- /dev/null +++ b/defaults/main/user_create.yml @@ -0,0 +1,9 @@ +--- +synology_dsm_new_user_name: automated_user1 +synology_dsm_new_user_description: Automatically created test user +synology_dsm_new_user_email: "" +synology_dsm_new_user_cnt_chg_pw: false +synology_dsm_new_user_expired: normal +synology_dsm_new_user_notify_by_email: false +synology_dsm_new_user_send_pw: false +synology_dsm_new_user_pass: dXNlX2Ffc3Ryb25nX3Bhc3N3b3JkX2xpa2VfdGhpcw== diff --git a/defaults/main/user_delete.yml b/defaults/main/user_delete.yml new file mode 100644 index 0000000..b2d14cd --- /dev/null +++ b/defaults/main/user_delete.yml @@ -0,0 +1,4 @@ +--- +synology_dsm_users_to_delete: + - "to_be_deleted_user1" + - "to_be_deleted_user2" diff --git a/filter_plugins/expanders.py b/filter_plugins/expanders.py new file mode 100644 index 0000000..2f542fe --- /dev/null +++ b/filter_plugins/expanders.py @@ -0,0 +1,273 @@ +# NOTE: ansible doesn't support importing from other files in the plugins dir +# so we keep all the expanders in the same file to avoid having copies of +# the common functions + +class FilterModule(object): + def filters(self): + return { + 'expand_bandwidths': exp_bandwidths, + 'expand_permissions': exp_permissions, + 'expand_quotas': exp_quotas, + 'expand_rules': exp_rules, + 'expand_users': exp_users + } + +# --------------------- +# ---- Expanders ------ +# --------------------- + +def exp_permissions(inlist, defaults): + expandables = [ + { + 'front_name': 'share_dir', + 'back_name': 'name', + 'required': True + }, + { + 'front_name': 'writable', + 'back_name': 'is_writable', + 'required': False + }, + { + 'front_name': 'readonly', + 'back_name': 'is_readonly', + 'required': False + }, + { + 'front_name': 'deny', + 'back_name': 'is_deny', + 'required': False + }, + { + 'front_name': 'custom', + 'back_name': 'is_custom', + 'required': False + } + ] + + return expand_list(inlist, 'permissions', expandables, defaults) + +def exp_rules(inlist, defaults): + expandables = [ + { + 'front_name': 'type', + 'back_name': 'entity_type', + 'required': False + }, + { + 'front_name': 'entity', + 'back_name': 'entity_name', + 'required': False + }, + { + 'front_name': 'app', + 'back_name': 'app_id', + 'required': True + } + ] + + return expand_list(inlist, 'rules', expandables, defaults) + +def exp_quotas(inlist, defaults): + expandables = [ + { + 'front_name': 'share_dir', + 'back_name': 'share', + 'required': True + }, + { + 'front_name': 'quota', + 'back_name': 'quota', + 'required': False + } + ] + + return expand_list(inlist, 'user_quota', expandables, defaults) + +def exp_bandwidths(inlist, defaults): + expandables = [ + { + 'front_name': 'name', + 'back_name': 'name', + 'required': False + }, + { + 'front_name': 'upload_result', + 'back_name': 'upload_result', + 'required': False + }, + { + 'front_name': 'download_result', + 'back_name': 'download_result', + 'required': False + }, + { + 'front_name': 'upload_limit_1', + 'back_name': 'upload_limit_1', + 'required': False + }, + { + 'front_name': 'download_limit_1', + 'back_name': 'download_limit_1', + 'required': False + }, + { + 'front_name': 'upload_limit_2', + 'back_name': 'upload_limit_2', + 'required': False + }, + { + 'front_name': 'download_limit_2', + 'back_name': 'download_limit_2', + 'required': False + }, + { + 'front_name': 'policy', + 'back_name': 'policy', + 'required': False + }, + { + 'front_name': 'protocol', + 'back_name': 'protocol', + 'required': False + }, + { + 'front_name': 'protocol_ui', + 'back_name': 'protocol_ui', + 'required': False + }, + { + 'front_name': 'owner_type', + 'back_name': 'owner_type', + 'required': False + }, + { + 'front_name': 'schedule_plan', + 'back_name': 'schedule_plan', + 'required': False + } + ] + + return expand_list(inlist, 'bandwidths', expandables, defaults) + +def exp_users(inlist): + expandables = [ + { + 'front_name': 'name' + } + ] + + return expand_list(inlist, 'name', expandables, fmt=['simple']) + +# --------------------- +# ----- Common -------- +# --------------------- + +def expand_list(inlist, keyname, expandables, defaults={}, fmt=[]): + """[summary] + Output is a a dictionary of an element that has an array + of elements each has expandables set to the inlist values + and for any optional value, revert to the default list. + Example: + inlist = [{"name": "abc", "writable": True},{"name":"def", "readonly": False}] + keyname = "permissions" + expandables = {"name": "required", "writable": "optional", "readonly": "optional"} + defaults = {"writable": True, "readonly": True} + + Arguments: + inlist {list(dict)} -- a list of the elements that will be expanded + keyname {string} -- a string of the output key name + expandables {list(dict)} -- a list of the expandables names, + each has value that influences how the processing + occurs, ie: optional would fallback to the defaults + and required would not fallback to the defaults + NOTE: an optional value is a fallback-able one + defaults {dict} -- default values of the optional exapandables + fmt {list(string)} -- format options that influces the final shape of the output + a `simple` formatis one that doesn't have a key + just a plain value list + + """ + outstr = "\"{}\": [\n".format(keyname) + + for elem, has_more in lookahead(inlist): + if ('simple' in fmt): + outstr += get_simple_elem_str(elem, expandables, defaults) + else: + outstr += get_elem_str(elem, expandables, defaults) + + if (has_more): + outstr += " ,\n" + else: + # last element + pass + + outstr += "]" + return outstr + +def get_elem_str(elem, expandables, defaults): + elemstr = " {\n" + + for expandable, has_more in lookahead(expandables): + if expandable['required'] == True: + value = elem[expandable['front_name']] + value = quote(value) + elemstr += " \"{}\": {}".format(expandable['back_name'], value) + + else: + if expandable['front_name'] in elem: + value = elem[expandable['front_name']] + else: + value = defaults[expandable['front_name']] + + value = quote(value) + elemstr += " \"{}\": {}".format(expandable['back_name'], value) + + if (has_more): + elemstr += ",\n" + else: + # last element + elemstr += "\n" + + elemstr += " }\n" + + return elemstr + +def get_simple_elem_str(elem, expandables, defaults): + elemstr = "" + + # NOTE: There should be only one expandable + for expandable in expandables: + value = elem[expandable['front_name']] + value = quote(value) + elemstr += " {}".format(value) + + return elemstr + + +def quote(value): + if type(value) == bool: + if (value): + return "true" + else: + return "false" + elif type(value) == int: + return value + else: + return "\"{}\"".format(value) + +def lookahead(iterable): + """Pass through all values from the given iterable, augmented by the + information if there are more values to come after the current one + (True), or if it is the last value (False). + """ + # Get an iterator and pull the first value. + it = iter(iterable) + last = next(it) + # Run the iterator to exhaustion (starting from the second value). + for val in it: + # Report the *previous* value (more to come). + yield last, True + last = val + # Report the last value. + yield last, False \ No newline at end of file diff --git a/tasks/login.yml b/tasks/api/auth/login.yml similarity index 73% rename from tasks/login.yml rename to tasks/api/auth/login.yml index 9d59b66..836a837 100644 --- a/tasks/login.yml +++ b/tasks/api/auth/login.yml @@ -6,8 +6,8 @@ api_version: 3 api_method: login api_params: - account: '{{ synology_dsm_username }}' - passwd: '{{ synology_dsm_password }}' + account: '{{ synology_dsm_login_user }}' + passwd: '{{ synology_dsm_login_pass | b64decode }}' register: synology_dsm_login_response - set_fact: diff --git a/tasks/api/auth/logout.yml b/tasks/api/auth/logout.yml new file mode 100644 index 0000000..4d0d4f3 --- /dev/null +++ b/tasks/api/auth/logout.yml @@ -0,0 +1,9 @@ +--- +# We are not logging out from a specific session, so that we can utilize any API +# That may not be the best security practice +- name: Logout + synology_dsm_api_request: + cgi_name: auth.cgi + api_name: SYNO.API.Auth + api_version: 3 + api_method: logout diff --git a/tasks/api/info.yml b/tasks/api/info.yml new file mode 100644 index 0000000..ad6aa97 --- /dev/null +++ b/tasks/api/info.yml @@ -0,0 +1,9 @@ +--- +- name: Query API info + synology_dsm_api_request: + cgi_name: query.cgi + api_name: SYNO.API.Info + api_method: query + api_params: + query: all + diff --git a/tasks/core/app_priv/rules/delete.yml b/tasks/core/app_priv/rules/delete.yml new file mode 100644 index 0000000..863db33 --- /dev/null +++ b/tasks/core/app_priv/rules/delete.yml @@ -0,0 +1,18 @@ +--- +- name: Delete app_priv of {{ user_name }} for {{ app_name }} + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.AppPriv.Rule", + "method": "delete", + "version": "1", + {{ rules | expand_rules(rules_defaults) }} + } + ] diff --git a/tasks/core/bandwidth_control/set.yml b/tasks/core/bandwidth_control/set.yml new file mode 100644 index 0000000..c5c7952 --- /dev/null +++ b/tasks/core/bandwidth_control/set.yml @@ -0,0 +1,18 @@ +--- +- name: Set bandwidths + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.BandwidthControl", + "method": "set", + "version": "1", + {{ bandwidths | expand_bandwidths(bandwidths_defaults) }} + } + ] diff --git a/tasks/core/fileserv/afp/set.yml b/tasks/core/fileserv/afp/set.yml new file mode 100644 index 0000000..b24b456 --- /dev/null +++ b/tasks/core/fileserv/afp/set.yml @@ -0,0 +1,19 @@ +--- +- name: Set AFP service + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api":"SYNO.Core.FileServ.AFP", + "method":"set", + "version":"1", + "enable_afp": {{ synology_dsm_afp_enable | to_json }}, + "afp_transfer_log_enable": {{ synology_dsm_afp_enable_transfer_log | to_json }} + } + ] diff --git a/tasks/core/fileserv/nfs/set.yml b/tasks/core/fileserv/nfs/set.yml new file mode 100644 index 0000000..83041fb --- /dev/null +++ b/tasks/core/fileserv/nfs/set.yml @@ -0,0 +1,19 @@ +--- +- name: Set NFS service + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [{ + "api":"SYNO.Core.FileServ.NFS", + "method":"set", + "version":"2", + "enable_nfs": {{ synology_dsm_nfs_enable | to_json }}, + "enable_nfs_v4": {{ synology_dsm_nfs_enable_v4 | to_json }}, + "enable_nfs_v4_1": {{ synology_dsm_nfs_enable_v4_1 | to_json }} + }] + diff --git a/tasks/core/fileserv/smb/set.yml b/tasks/core/fileserv/smb/set.yml new file mode 100644 index 0000000..a26c819 --- /dev/null +++ b/tasks/core/fileserv/smb/set.yml @@ -0,0 +1,19 @@ +--- +- name: Enable/Disable SMB service + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [{ + "api":"SYNO.Core.FileServ.SMB", + "method":"set", + "version":"3", + "enable_samba": {{ synology_dsm_smb_enable | to_json }}, + "workgroup": "{{ synology_dsm_smb_workgroup }}", + "disable_shadow_copy": {{ synology_dsm_smb_disable_shadow_copy | to_json }}, + "smb_transfer_log_enable": {{ synology_dsm_smb_enable_transfer_log | to_json }} + }] diff --git a/tasks/core/otp/enforce_policy/get.yml b/tasks/core/otp/enforce_policy/get.yml new file mode 100644 index 0000000..94639c8 --- /dev/null +++ b/tasks/core/otp/enforce_policy/get.yml @@ -0,0 +1,17 @@ +--- +- name: Get OTP Enforce Policy + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.OTP.EnforcePolicy", + "method": "get", + "version": "1" + } + ] diff --git a/tasks/core/otp/enforce_policy/set.yml b/tasks/core/otp/enforce_policy/set.yml new file mode 100644 index 0000000..7e0b669 --- /dev/null +++ b/tasks/core/otp/enforce_policy/set.yml @@ -0,0 +1,19 @@ +--- +- name: Set OTP Enforce Policy + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.OTP.EnforcePolicy", + "method": "set", + "version": "1", + "enable_otp_enforcement": false, + "otp_enforce_option": "none" + } + ] diff --git a/tasks/package_sources.yml b/tasks/core/package/feed/_add.yml similarity index 57% rename from tasks/package_sources.yml rename to tasks/core/package/feed/_add.yml index 748a16c..e8aa88d 100644 --- a/tasks/package_sources.yml +++ b/tasks/core/package/feed/_add.yml @@ -1,11 +1,4 @@ --- -- name: List package sources - synology_dsm_api_request: - api_name: SYNO.Core.Package.Feed - api_method: list - request_method: POST - register: synology_dsm_package_sources_list - - name: Package sources synology_dsm_api_request: api_name: SYNO.Core.Package.Feed @@ -18,10 +11,3 @@ loop: '{{ synology_dsm_package_sources }}' loop_control: label: '{{ item.name }}' - -#- name: List installed packages -# synology_dsm_api_request: -# api_name: SYNO.Core.Package -# api_method: list -# api_version: 2 -# register: synology_dsm_package_list diff --git a/tasks/core/package/feed/add.yml b/tasks/core/package/feed/add.yml new file mode 100644 index 0000000..88ddc9d --- /dev/null +++ b/tasks/core/package/feed/add.yml @@ -0,0 +1,11 @@ +--- +- set_fact: + globals: {} + +- include_tasks: list.yml + vars: + return_name: synology_dsm_package_list + +- include_tasks: _add.yml + vars: + synology_dsm_package_list: globals.synology_dsm_package_list diff --git a/tasks/core/package/feed/list.yml b/tasks/core/package/feed/list.yml new file mode 100644 index 0000000..e937532 --- /dev/null +++ b/tasks/core/package/feed/list.yml @@ -0,0 +1,14 @@ +--- +- set_fact: + return_name: default_return_name + +- name: List package sources + synology_dsm_api_request: + api_name: SYNO.Core.Package.Feed + api_method: list + request_method: POST + register: synology_dsm_package_sources_list + +- name: update_facts + set_fact: + globals: "{{ globals|combine({ return_name: reg }) }}" diff --git a/tasks/core/package/list.yml b/tasks/core/package/list.yml new file mode 100644 index 0000000..67ed9e8 --- /dev/null +++ b/tasks/core/package/list.yml @@ -0,0 +1,14 @@ +--- +- set_fact: + return_name: default_return_name + +- name: List installed packages + synology_dsm_api_request: + api_name: SYNO.Core.Package + api_method: list + api_version: 2 + register: reg + +- name: update_facts + set_fact: + globals: "{{ globals|combine({ return_name: reg }) }}" diff --git a/tasks/core/quota/set.yml b/tasks/core/quota/set.yml new file mode 100644 index 0000000..36be523 --- /dev/null +++ b/tasks/core/quota/set.yml @@ -0,0 +1,29 @@ +--- +- name: Set quota + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Quota", + "method": "set", + "version": 1, + "name": "{{ user_name }}", + {{ quotas | expand_quotas(quotas_defaults) }} + } + ] + +# Errors: +# "code": 3300, +# "errors": { +# "fail_share": "shared_folder" +# } => username is not available +# "code": 3302, +# "errors": { +# "fail_share": "shared_folder2" +# } => shared folder is not available diff --git a/tasks/core/share/permission/set.yml b/tasks/core/share/permission/set.yml new file mode 100644 index 0000000..2ae1f0a --- /dev/null +++ b/tasks/core/share/permission/set.yml @@ -0,0 +1,20 @@ +--- +- name: Set share Directory Permission + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Share.Permission", + "method": "set_by_user_group", + "version": 1, + "name": "{{ user_name }}", + "user_group_type": "local_user", + {{ permissions | expand_permissions(permissions_defaults) }} + } + ] diff --git a/tasks/core/storage/volume/list.yml b/tasks/core/storage/volume/list.yml new file mode 100644 index 0000000..9f0d5e6 --- /dev/null +++ b/tasks/core/storage/volume/list.yml @@ -0,0 +1,20 @@ +--- +- name: List Storage Volumes + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Storage.Volume", + "method": "list", + "version": "1", + "offset": 0, + "limit": -1, + "location": "internal" + } + ] diff --git a/tasks/core/terminal/set.yml b/tasks/core/terminal/set.yml new file mode 100644 index 0000000..36e7741 --- /dev/null +++ b/tasks/core/terminal/set.yml @@ -0,0 +1,20 @@ +--- +- name: Set SSH/Telnet + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api":"SYNO.Core.Terminal", + "method":"set", + "version":"3", + "enable_telnet": {{ synology_dsm_telnet_enable | to_json }}, + "enable_ssh": {{ synology_dsm_ssh_enable | to_json }}, + "ssh_port": {{ synology_dsm_ssh_port }} + } + ] diff --git a/tasks/core/user/_create.yml b/tasks/core/user/_create.yml new file mode 100644 index 0000000..41772fb --- /dev/null +++ b/tasks/core/user/_create.yml @@ -0,0 +1,27 @@ +--- +- name: Create a user + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User", + "method": "create", + "version": "1", + "name": "{{ synology_dsm_new_user_name }}", + "description": "{{ synology_dsm_new_user_description }}", + "email": "{{ synology_dsm_new_user_email }}", + "cannot_chg_passwd": {{ synology_dsm_new_user_cnt_chg_pw | to_json }}, + "expired": "{{ synology_dsm_new_user_expired }}", + "notify_by_email": {{ synology_dsm_new_user_notify_by_email | to_json }}, + "send_password": {{ synology_dsm_new_user_send_pw | to_json }}, + "password": "{{ synology_dsm_new_user_pass | b64decode }}" + } + ] + +# error 3107: user already exists diff --git a/tasks/core/user/_delete.yml b/tasks/core/user/_delete.yml new file mode 100644 index 0000000..bea5578 --- /dev/null +++ b/tasks/core/user/_delete.yml @@ -0,0 +1,21 @@ +--- +- name: Delete { {{ del_users | expand_users }} } + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User", + "method": "delete", + "version": "1", + {{ del_users | expand_users }} + } + ] + +# 3101: means the user may not be locate-able +# returns 3102 if success diff --git a/tasks/core/user/_set.yml b/tasks/core/user/_set.yml new file mode 100644 index 0000000..662a974 --- /dev/null +++ b/tasks/core/user/_set.yml @@ -0,0 +1,30 @@ +--- +- name: Edit a user + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User", + "method": "set", + "version": "1", + "name": "{{ user_name_old }}", + "new_name": "{{ user_name }}", + "description": "{{ user_description }}", + "email": "{{ user_email }}", + "expired": "{{ user_expiration }}", + "cannot_chg_passwd": {{ user_cnt_chg_pw | to_json }}, + "password": "{{ user_pass | b64decode }}" + } + ] + +# expired: value is either "now", "normal" or a date +# - "normal" means never expires +# - "now" means to expire immediately +# - a date is a string similar to "2020/4/27" +# password: is an optional param diff --git a/tasks/core/user/create.yml b/tasks/core/user/create.yml new file mode 100644 index 0000000..7512df5 --- /dev/null +++ b/tasks/core/user/create.yml @@ -0,0 +1,96 @@ +--- +- set_fact: + globals: {} + +- include_tasks: list.yml + vars: + return_name: synology_dsm_user_list + +# - debug: +# var: synology_dsm_user_list + +- assert: + that: + - "{\"name\": \"{{ synology_dsm_new_user_name }}\"} not in globals.synology_dsm_user_list.json.data.users" + fail_msg: "User {{ synology_dsm_new_user_name }} already exists, please assign synology_dsm_new_user a different name" + success_msg: "User {{ synology_dsm_new_user_name }} is ready to be created" + +- include_tasks: _create.yml + +- include_tasks: ../share/permission/set.yml + vars: + user_name: "{{ synology_dsm_new_user_name }}" + permissions_defaults: + writable: false + readonly: false + deny: false + custom: false + permissions: + - share_dir: "shared_dir1" + - share_dir: "shared_dir2" + - share_dir: "shared_dir3" + +- include_tasks: ../app_priv/rules/delete.yml + vars: + rules_defaults: + type: user + entity: "{{ synology_dsm_new_user_name }}" + rules: + - app: "SYNO.FTP" + - app: "SYNO.Desktop" + - app: "SYNO.SDS.App.FileStation3.Instance" + - app: "SYNO.Photo.AppInstance" + - app: "SYNO.SDS.Drive.Application" + - app: "SYNO.TextEditor.Application" + - app: "SYNO.Finder.Application" + - app: "SYNO.SDS.Virtualization.Application" + - app: "SYNO.SDS.VideoStation.AppInstance" + - app: "SYNO.Rsync" + +- include_tasks: ../quota/set.yml + vars: + user_name: "{{ synology_dsm_new_user_name }}" + quotas_defaults: + quota: 0 + quotas: + - share_dir: "shared_dir1" + - share_dir: "shared_dir2" + - share_dir: "shared_dir3" + +- include_tasks: ../bandwidth_control/set.yml + vars: + bandwidths_defaults: + name: "{{ synology_dsm_new_user_name }}" + upload_result: "" + download_result: "" + upload_limit_1: 0 + download_limit_1: 0 + upload_limit_2: 0 + download_limit_2: 0 + policy: "notexist" + owner_type: "local_user" + schedule_plan: "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + bandwidths: + - protocol: "FileStation" + protocol_ui: "FileStation" + - protocol: "FTP" + protocol_ui: "FTP" + - protocol: "NetworkBackup" + protocol_ui: "NetworkBackup" + - protocol: "CloudStation" + protocol_ui: "Synology Drive Server" + +- include_tasks: ../group/member/add.yml + vars: + user_name: "{{ synology_dsm_new_user_name }}" + group_name: "{{ item }}" + with_list: + - administrators + +- include_tasks: ../group/member/remove.yml + vars: + user_name: "{{ synology_dsm_new_user_name }}" + group_name: "{{ item }}" + with_list: + - group1 + - group2 diff --git a/tasks/core/user/delete.yml b/tasks/core/user/delete.yml new file mode 100644 index 0000000..f4f8d56 --- /dev/null +++ b/tasks/core/user/delete.yml @@ -0,0 +1,34 @@ +--- +# use globals to capture return registers from nested tasks +- set_fact: + globals: {} + +- include_tasks: list.yml + vars: + return_name: synology_dsm_user_list + +# - debug: +# var: globals.synology_dsm_user_list + +- assert: + that: + - "{\"name\": \"{{ item }}\"} in globals.synology_dsm_user_list.json.data.users" + fail_msg: "User doesn't exist, please be careful of the desired user to be deleted" + success_msg: "User is ready to be deleted" + with_list: + - toBeDeletedUser1 + - toBeDeletedUser2 + - toBeDeletedUser3 + - toBeDeletedUser4 + +# Even though this request is mandatory from the UI, +# it is not needed for the webapi interface +# - include_tasks: password_confirm/auth.yml + +- include_tasks: _delete.yml + vars: + del_users: + - name: toBeDeletedUser1 + - name: toBeDeletedUser2 + - name: toBeDeletedUser3 + - name: toBeDeletedUser4 diff --git a/tasks/core/user/group/member/add.yml b/tasks/core/user/group/member/add.yml new file mode 100644 index 0000000..94ef7b9 --- /dev/null +++ b/tasks/core/user/group/member/add.yml @@ -0,0 +1,19 @@ +--- +- name: Add {{ user_name }} to {{ group_name }} + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Group.Member", + "method": "add", + "version": 1, + "group": "{{ group_name }}", + "member": "{{ user_name }}" + } + ] diff --git a/tasks/core/user/group/member/remove.yml b/tasks/core/user/group/member/remove.yml new file mode 100644 index 0000000..bed60e3 --- /dev/null +++ b/tasks/core/user/group/member/remove.yml @@ -0,0 +1,19 @@ +--- +- name: Remove {{ user_name }} from {{ group_name }} + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Group.Member", + "method": "remove", + "version": 1, + "group": "{{ group_name }}", + "member": "{{ user_name }}" + } + ] diff --git a/tasks/core/user/home/get.yml b/tasks/core/user/home/get.yml new file mode 100644 index 0000000..0fd561e --- /dev/null +++ b/tasks/core/user/home/get.yml @@ -0,0 +1,20 @@ +--- +- name: Get User Home Settings + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User.Home", + "method": "get", + "version": "1", + "additional": [ + "personal_photo_enable" + ] + } + ] diff --git a/tasks/core/user/home/set.yml b/tasks/core/user/home/set.yml new file mode 100644 index 0000000..a6fb581 --- /dev/null +++ b/tasks/core/user/home/set.yml @@ -0,0 +1,9 @@ +- name: Set User Home Service + synology_dsm_api_request: + api_name: SYNO.Core.User.Home + api_method: set + request_method: POST + api_params: + enable: '{{ synology_dsm_user_home_service_enable | to_json }}' + location: '{{ synology_dsm_user_home_location }}' + enable_recycle_bin: '{{ synology_dsm_user_home_enable_recycle_bin | to_json }}' diff --git a/tasks/core/user/list.yml b/tasks/core/user/list.yml new file mode 100644 index 0000000..3a89977 --- /dev/null +++ b/tasks/core/user/list.yml @@ -0,0 +1,23 @@ +--- +# Use a default to avoid the task being broken if called without +# a preset return_name +# TODO: consider using a conditional instead +- set_fact: + return_name: default_return_name + +- name: List users + synology_dsm_api_request: + api_name: SYNO.Core.User + api_method: list + request_method: POST +# additional: ["email", "description", "expired"] +# type: "local" +# offset: 0 +# limit: -1 + register: reg +# Use the additional keyword to specify the SELECT clause +# NOTE: The commented is only observed but not tested + +- name: update_facts + set_fact: + globals: "{{ globals|combine({ return_name: reg }) }}" diff --git a/tasks/core/user/password_confirm/auth.yml b/tasks/core/user/password_confirm/auth.yml new file mode 100644 index 0000000..232f88a --- /dev/null +++ b/tasks/core/user/password_confirm/auth.yml @@ -0,0 +1,19 @@ +--- +- name: Confirm Password + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User.PasswordConfirm", + "method": "auth", + "version": "1", + "password": "{{ synology_dsm_password}}" + } + ] + diff --git a/tasks/core/user/password_expiry/get.yml b/tasks/core/user/password_expiry/get.yml new file mode 100644 index 0000000..9c23161 --- /dev/null +++ b/tasks/core/user/password_expiry/get.yml @@ -0,0 +1,17 @@ +--- +- name: Get Password Expiration + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User.PasswordExpiry", + "method": "get", + "version": "1" + } + ] diff --git a/tasks/core/user/password_expiry/set.yml b/tasks/core/user/password_expiry/set.yml new file mode 100644 index 0000000..23c9c79 --- /dev/null +++ b/tasks/core/user/password_expiry/set.yml @@ -0,0 +1,18 @@ +--- +- name: Set Password Expiration + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User.PasswordExpiry", + "method": "set", + "version": "1", + "password_expire_enable": false + } + ] diff --git a/tasks/core/user/password_policy/get.yml b/tasks/core/user/password_policy/get.yml new file mode 100644 index 0000000..97b8aba --- /dev/null +++ b/tasks/core/user/password_policy/get.yml @@ -0,0 +1,18 @@ +--- +- name: Get Password Policy + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User.PasswordPolicy", + "method": "get", + "version": "1" + } + ] + diff --git a/tasks/core/user/password_policy/set.yml b/tasks/core/user/password_policy/set.yml new file mode 100644 index 0000000..b1a39d1 --- /dev/null +++ b/tasks/core/user/password_policy/set.yml @@ -0,0 +1,30 @@ +--- +- name: Set Password Policy + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.User.PasswordPolicy", + "method": "set", + "version": "1", + "enable_reset_passwd_by_email": false, + "password_must_change": false, + "strong_password": { + "exclude_username": true, + "included_numeric_char": false, + "included_special_char": false, + "min_length_enable": true, + "min_length": 6, + "mixed_case": true, + "exclude_common_password": false, + "exclude_history": false + } + } + ] + diff --git a/tasks/dsm/port_enable/ssh.yml b/tasks/dsm/port_enable/ssh.yml new file mode 100644 index 0000000..548d858 --- /dev/null +++ b/tasks/dsm/port_enable/ssh.yml @@ -0,0 +1,12 @@ +--- +- name: Open SSH port + synology_dsm_api_request: + api_name: SYNO.DSM.PortEnable + api_method: is_port_block + request_method: POST + api_params: + name: >- + ["SYNO.SDS.AdminCenter.Terminal.SSH"] + isPkg: 'false' + isDirectID: 'false' + when: synology_dsm_ssh_enable | bool diff --git a/tasks/file_services.yml b/tasks/file_services.yml deleted file mode 100644 index 79afd95..0000000 --- a/tasks/file_services.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- -- name: Enable/Disable NFS service - synology_dsm_api_request: - api_name: SYNO.Entry.Request - api_method: request - request_method: POST - api_params: - stop_on_error: 'false' - mode: sequential - compound: >- - [{ - "api":"SYNO.Core.FileServ.NFS", - "method":"set", - "version":"2", - "enable_nfs":{{ synology_dsm_nfs_enable | to_json }}, - "enable_nfs_v4":{{ synology_dsm_nfs_enable_v4 | to_json }}, - "enable_nfs_v4_1":{{ synology_dsm_nfs_enable_v4_1 | to_json }} - }] - -- name: Enable/Disable SMB service - synology_dsm_api_request: - api_name: SYNO.Entry.Request - api_method: request - request_method: POST - api_params: - stop_on_error: 'false' - mode: sequential - compound: >- - [{ - "api":"SYNO.Core.FileServ.SMB", - "method":"set", - "version":"3", - "enable_samba":{{ synology_dsm_smb_enable | to_json }}, - "workgroup":"{{ synology_dsm_smb_workgroup }}", - "disable_shadow_copy":{{ synology_dsm_smb_disable_shadow_copy | to_json }}, - "smb_transfer_log_enable":{{ synology_dsm_smb_enable_transfer_log | to_json }} - }] - -- name: Enable/Disable AFP service - synology_dsm_api_request: - api_name: SYNO.Entry.Request - api_method: request - request_method: POST - api_params: - stop_on_error: 'false' - mode: sequential - compound: >- - [{ - "api":"SYNO.Core.FileServ.AFP", - "method":"set", - "version":"1", - "enable_afp":{{ synology_dsm_afp_enable | to_json }}, - "afp_transfer_log_enable":{{ synology_dsm_afp_enable_transfer_log | to_json }} - }] diff --git a/tasks/main.yml b/tasks/main.yml index 025d9c5..c1b7bcc 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -5,25 +5,35 @@ base_url: '{{ synology_dsm_base_url }}' login_cookie: '{{ synology_dsm_login_cookie | default(omit) }}' block: - - include_tasks: login.yml + - include_tasks: api/auth/login.yml - #- name: Query API info - # synology_dsm_api_request: - # cgi_name: query.cgi - # api_name: SYNO.API.Info - # api_method: query - # api_params: - # query: all + # Figure out the API + # - include_tasks: api/info.yml - - name: Query system status - synology_dsm_api_request: - api_name: SYNO.Core.System.Status - api_method: get + # Get system status info + - include_tasks: system/status.yml - - include_tasks: terminal.yml + # Control the terminal access + # - include_tasks: terminal.yml - - include_tasks: users.yml + # List all users + # - include_tasks: core/user/list.yml - - include_tasks: package_sources.yml + # Create a user + # - include_tasks: core/user/create.yml - - include_tasks: file_services.yml + # Delete users + # - include_tasks: core/user/delete.yml + + # Set mail configurations + # - include_tasks: notif/mail/conf/set.yml + + # Add a package source + # - include_tasks: core/package/feed/add.yml + + # Set specific file services & protocols + # - include_tasks: core/fileserv/afp/set.yml + # - include_tasks: core/fileserv/nfs/set.yml + # - include_tasks: core/fileserv/smb/set.yml + + - include_tasks: api/auth/logout.yml diff --git a/tasks/notif/mail/conf/get.yml b/tasks/notif/mail/conf/get.yml new file mode 100644 index 0000000..d62f395 --- /dev/null +++ b/tasks/notif/mail/conf/get.yml @@ -0,0 +1,17 @@ +--- +- name: Setup email SMTP + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.Mail.Conf", + "method": "get", + "version": 1 + } + ] diff --git a/tasks/notif/mail/conf/set.yml b/tasks/notif/mail/conf/set.yml new file mode 100644 index 0000000..d00b46a --- /dev/null +++ b/tasks/notif/mail/conf/set.yml @@ -0,0 +1,36 @@ +--- +- name: Setup email SMTP + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.Mail.Conf", + "method": "set", + "version": 1, + "enable_mail": {{ synology_dsm_notif_mail_enable | to_json }}, + "mail": [ + "{{ synology_dsm_notif_mail_receipent }}" + ], + "subject_prefix": "{{ synology_dsm_notif_mail_prefix }}", + "smtp_info": { + "server": "{{ synology_dsm_notif_mail_server }}", + "port": {{ synology_dsm_notif_mail_port }}, + "ssl": {{ synology_dsm_notif_mail_ssl | to_json }}, + "oauth": {{ synology_dsm_notif_mail_oauth | to_json }} + }, + "smtp_auth": { + "enable": {{ synology_dsm_notif_mail_auth_enable | to_json }}, + "user": "{{ synology_dsm_notif_mail_auth_user }}", + "pass": "{{ synology_dsm_notif_mail_auth_pass | b64decode }}" + }, + "send_welcome_mail": {{ synology_dsm_notif_mail_welcome_mail | to_json }}, + "sender_name": "{{ synology_dsm_notif_mail_sender_name }}", + "sender_mail": "{{ synology_dsm_notif_mail_sender_mail }}" + } + ] diff --git a/tasks/notif/push/conf/get.yml b/tasks/notif/push/conf/get.yml new file mode 100644 index 0000000..93a9794 --- /dev/null +++ b/tasks/notif/push/conf/get.yml @@ -0,0 +1,17 @@ +--- +- name: Get Push conf + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.Push.Conf", + "method": "get", + "version": 1 + } + ] \ No newline at end of file diff --git a/tasks/notif/push/conf/set.yml b/tasks/notif/push/conf/set.yml new file mode 100644 index 0000000..a1a01c9 --- /dev/null +++ b/tasks/notif/push/conf/set.yml @@ -0,0 +1,18 @@ +--- +- name: Set Push conf + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.Push.Conf", + "method": "set", + "version": 1, + "mobile_enable": false + } + ] \ No newline at end of file diff --git a/tasks/notif/push/mail/get.yml b/tasks/notif/push/mail/get.yml new file mode 100644 index 0000000..62536a6 --- /dev/null +++ b/tasks/notif/push/mail/get.yml @@ -0,0 +1,17 @@ +--- +- name: Get Push conf + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.Push.Mail", + "method": "get", + "version": 1 + } + ] \ No newline at end of file diff --git a/tasks/notif/push/mail/set.yml b/tasks/notif/push/mail/set.yml new file mode 100644 index 0000000..bcf4490 --- /dev/null +++ b/tasks/notif/push/mail/set.yml @@ -0,0 +1,19 @@ +--- +- name: Set Push conf + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.Push.Mail", + "method": "set", + "version": 1, + "enable_mail": false, + "mail": [] + } + ] \ No newline at end of file diff --git a/tasks/notif/sms/conf/get.yml b/tasks/notif/sms/conf/get.yml new file mode 100644 index 0000000..8c12491 --- /dev/null +++ b/tasks/notif/sms/conf/get.yml @@ -0,0 +1,17 @@ +--- +- name: Get SMS conf + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.SMS.Conf", + "method": "get", + "version": "2" + } + ] \ No newline at end of file diff --git a/tasks/notif/sms/conf/set.yml b/tasks/notif/sms/conf/set.yml new file mode 100644 index 0000000..770d398 --- /dev/null +++ b/tasks/notif/sms/conf/set.yml @@ -0,0 +1,23 @@ +--- +- name: Set SMS conf + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.Core.Notification.SMS.Conf", + "method": "set", + "version": "2", + "enable_sms": false, + "phone_info": [ + {}, + {} + ], + "msg_interval": 0 + } + ] \ No newline at end of file diff --git a/tasks/s2s/server/pair/list.yml b/tasks/s2s/server/pair/list.yml new file mode 100644 index 0000000..ae64491 --- /dev/null +++ b/tasks/s2s/server/pair/list.yml @@ -0,0 +1,20 @@ +--- +- name: List S2S Server Pairs + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.S2S.Server.Pair", + "method": "list", + "version": "1", + "additional": [ + "sync_shares" + ] + } + ] diff --git a/tasks/system/status.yml b/tasks/system/status.yml new file mode 100644 index 0000000..aed0ae1 --- /dev/null +++ b/tasks/system/status.yml @@ -0,0 +1,4 @@ +- name: Query system status + synology_dsm_api_request: + api_name: SYNO.Core.System.Status + api_method: get diff --git a/tasks/terminal.yml b/tasks/terminal.yml index 9d51711..b18674d 100644 --- a/tasks/terminal.yml +++ b/tasks/terminal.yml @@ -1,24 +1,5 @@ --- -- name: Enable/Disable SSH/Telnet - synology_dsm_api_request: - api_name: SYNO.Entry.Request - api_method: request - request_method: POST - api_params: - stop_on_error: 'false' - mode: sequential - compound: >- - [{"api":"SYNO.Core.Terminal","method":"set","version":"3","enable_telnet":{{ synology_dsm_telnet_enable | to_json }},"enable_ssh":{{ synology_dsm_ssh_enable | to_json }},"ssh_port":{{ synology_dsm_ssh_port }}}] +- include_tasks: core/terminal/set.yml # XXX: this may not be needed at all -- name: Open SSH port - synology_dsm_api_request: - api_name: SYNO.DSM.PortEnable - api_method: is_port_block - request_method: POST - api_params: - name: >- - ["SYNO.SDS.AdminCenter.Terminal.SSH"] - isPkg: 'false' - isDirectID: 'false' - when: synology_dsm_ssh_enable | bool +- include_tasks: dsm/port_enable/ssh.yml diff --git a/tasks/users.yml b/tasks/users.yml deleted file mode 100644 index 349615c..0000000 --- a/tasks/users.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: Enable/Disable User Home Service - synology_dsm_api_request: - api_name: SYNO.Core.User.Home - api_method: set - request_method: POST - api_params: - enable: '{{ synology_dsm_user_home_service_enable | to_json }}' - location: '{{ synology_dsm_user_home_location }}' - enable_recycle_bin: '{{ synology_dsm_user_home_enable_recycle_bin | to_json }}' - -#- name: List users -# synology_dsm_api_request: -# api_name: SYNO.Core.User -# api_method: list -# request_method: POST -# register: synology_dsm_user_list diff --git a/tasks/vpnserver/management/account/apply.yml b/tasks/vpnserver/management/account/apply.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/account/load.yml b/tasks/vpnserver/management/account/load.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/connection/enum.yml b/tasks/vpnserver/management/connection/enum.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/connection/kick.yml b/tasks/vpnserver/management/connection/kick.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/interface/apply.yml b/tasks/vpnserver/management/interface/apply.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/interface/load.yml b/tasks/vpnserver/management/interface/load.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/log/clear.yml b/tasks/vpnserver/management/log/clear.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/log/export.yml b/tasks/vpnserver/management/log/export.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/management/log/load.yml b/tasks/vpnserver/management/log/load.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/settings/certificate.yml b/tasks/vpnserver/settings/certificate.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/settings/config/apply.yml b/tasks/vpnserver/settings/config/apply.yml new file mode 100644 index 0000000..5bf0a90 --- /dev/null +++ b/tasks/vpnserver/settings/config/apply.yml @@ -0,0 +1,40 @@ +--- +- name: Apply VPN Settings + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.VPNServer.Settings.Config", + "method": "apply", + "version": "1", + "serv_type": "\"l2tp\"", + "serv_enable": "true", + "serv_ip": "\"10.120.0.0\"", + "serv_range": "5", + "auth_type": "2", + "auth_conn": "3", + "mtu": "\"1400\"", + "dns_check": "false", + "dns": "\"8.8.8.8\"", + "preshared_key": "\"STRONG_PASSWORD\"", + "preshared_key_confirm": "\"STRONG_PASSWORD\"", + "sha2_truncbug": "false", + "kernel_mode": "true" + } + ] + +# documentation +# l2tp is one of the three available vpn services +# +# serv_ip: a value in x.x.x.0, +# serv_range: max connection number, a value in [5,10,15,20,25,30], +# auth_type: 0 for PAP, 2 for MS_CHAP v2, +# auth_conn: max number of connections, +# dns_check: use manual dns, +# sha2_truncbug: sha256 compatible mode, diff --git a/tasks/vpnserver/settings/config/load.yml b/tasks/vpnserver/settings/config/load.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/vpnserver/settings/config/status_load.yml b/tasks/vpnserver/settings/config/status_load.yml new file mode 100644 index 0000000..e69de29 diff --git a/tasks/webstation/default/get.yml b/tasks/webstation/default/get.yml new file mode 100644 index 0000000..023c6da --- /dev/null +++ b/tasks/webstation/default/get.yml @@ -0,0 +1,18 @@ +--- +- name: Get Webstation Default + synology_dsm_api_request: + api_name: SYNO.Entry.Request + api_method: request + request_method: POST + api_params: + stop_on_error: 'false' + mode: sequential + compound: >- + [ + { + "api": "SYNO.WebStation.Default", + "method": "get", + "version": "1" + ] + } + ]