description:
       - Dictionary with key/value pairs. The actual names and meaning of pairs
         depends on the used mode.
-      - 'settings' mode:
-        option: Option/path in JSON API (url).
-        value: A new value to replace the current one.
-      - 'access_control' mode:
-        None - not yet implemented - placeholder only.
+      - settings mode:
+        option - Option/path in JSON API (url).
+        value - A new value to replace the current one.
+      - access_control mode:
+        account_id - The unique ID of the account - the default rancher admin
+        has '1a1'. Better way would be to just create arbitrary username and
+        set credentials for that, but due to time constraints, the route with
+        an ID is simpler. The designated '1a1' could be hardcoded and hidden
+        but if the user will want to use some other account (there are many),
+        then it can be just changed to some other ID.
+        password - A new password in a plaintext.
     required: true
   timeout:
     description:
 
 @_decorate_rancher_api_request
 def set_rancher_api_value(url, payload, headers=None, timeout=default_timeout,
-                          username=None, password=None):
+                          username=None, password=None, method='PUT'):
+
+    if method == 'PUT':
+        request_set_method = requests.put
+    elif method == 'POST':
+        request_set_method = requests.post
+    else:
+        raise ModeError('ERROR: Wrong request method: %s' % str(method))
 
     if username and password:
-        return requests.put(url, headers=headers,
-                            timeout=timeout,
-                            allow_redirects=False,
-                            data=json.dumps(payload),
-                            auth=(username, password))
+        return request_set_method(url, headers=headers,
+                                  timeout=timeout,
+                                  allow_redirects=False,
+                                  data=json.dumps(payload),
+                                  auth=(username, password))
     else:
-        return requests.put(url, headers=headers,
-                            timeout=timeout,
-                            allow_redirects=False,
-                            data=json.dumps(payload))
+        return request_set_method(url, headers=headers,
+                                  timeout=timeout,
+                                  allow_redirects=False,
+                                  data=json.dumps(payload))
 
 
 def create_rancher_api_url(server, mode, option):
     return None, None
 
 
+def mode_access_control(api_url, data=None, headers=None,
+                        timeout=default_timeout, access_key=None,
+                        secret_key=None, dry_run=False):
+
+    # returns true if local auth was enabled or false if passwd changed
+    def is_admin_enabled(json_data, password):
+        try:
+            if json_data['type'] == "localAuthConfig" and \
+                    json_data['accessMode'] == "unrestricted" and \
+                    json_data['username'] == "admin" and \
+                    json_data['password'] == password and \
+                    json_data['enabled']:
+                return True
+        except Exception:
+            pass
+
+        try:
+            if json_data['type'] == "error" and \
+                    json_data['code'] == "IncorrectPassword":
+                return False
+        except Exception:
+            pass
+
+        # this should never happen
+        raise ModeError('ERROR: Unknown status of the local authentication')
+
+    def create_localauth_payload(password):
+        payload = {
+            "enabled": True,
+            "accessMode": "unrestricted",
+            "username": "admin",
+            "password": password
+        }
+
+        return payload
+
+    def get_admin_password_id():
+        # assemble request URL
+        request_url = api_url + 'accounts/' + data['account_id'].strip('/') \
+            + '/credentials'
+
+        # API get current value
+        try:
+            json_response = get_rancher_api_value(request_url,
+                                                  username=access_key,
+                                                  password=secret_key,
+                                                  headers=headers,
+                                                  timeout=timeout)
+        except requests.HTTPError as e:
+            raise ModeError(str(e))
+        except requests.Timeout as e:
+            raise ModeError(str(e))
+
+        if not json_response:
+            raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in '
+                            + 'the response')
+
+        try:
+            for item in json_response['data']:
+                if item['type'] == 'password' and \
+                        item['accountId'] == data['account_id']:
+                    return item['id']
+        except Exception:
+            pass
+
+        return None
+
+    # check if data contains all required fields
+    try:
+        if not isinstance(data['account_id'], str) or data['account_id'] == '':
+            raise ModeError("ERROR: 'account_id' must contain an id of the "
+                            + "affected account")
+    except KeyError:
+        raise ModeError("ERROR: Mode 'access_control' requires the field: "
+                        + "'account_id': %s" % str(data))
+    try:
+        if not isinstance(data['password'], str) or data['password'] == '':
+            raise ModeError("ERROR: 'password' must contain some password")
+    except KeyError:
+        raise ModeError("ERROR: Mode 'access_control' requires the field: "
+                        + "'password': %s" % str(data))
+
+    # assemble request URL
+    request_url = api_url + 'localauthconfigs'
+
+    # API get current value
+    try:
+        json_response = get_rancher_api_value(request_url,
+                                              username=access_key,
+                                              password=secret_key,
+                                              headers=headers,
+                                              timeout=timeout)
+    except requests.HTTPError as e:
+        raise ModeError(str(e))
+    except requests.Timeout as e:
+        raise ModeError(str(e))
+
+    if not json_response:
+        raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in the '
+                        + 'response')
+
+    # we will check if local auth is enabled or not
+    enabled = False
+    try:
+        for item in json_response['data']:
+            if item['type'] == 'localAuthConfig' and \
+                    item['accessMode'] == 'unrestricted' and \
+                    item['enabled']:
+                enabled = True
+                break
+    except Exception:
+        enabled = False
+
+    if dry_run:
+        # we will not set anything, only signal potential change
+        if enabled:
+            changed = False
+        else:
+            changed = True
+    else:
+        # we will try to enable again with the same password
+        localauth_payload = create_localauth_payload(data['password'])
+        json_response = None
+        try:
+            json_response = set_rancher_api_value(request_url,
+                                                  localauth_payload,
+                                                  username=access_key,
+                                                  password=secret_key,
+                                                  headers=headers,
+                                                  method='POST',
+                                                  timeout=timeout)
+        except requests.HTTPError as e:
+            raise ModeError(str(e))
+        except requests.Timeout as e:
+            raise ModeError(str(e))
+
+        if not json_response:
+            raise ModeError('ERROR: BAD RESPONSE (PUT) - no json value in '
+                            + 'the response')
+
+        # we check if the admin was already set or not...
+        if enabled and is_admin_enabled(json_response, data['password']):
+            # it was enabled before and password is the same - no change
+            changed = False
+        elif is_admin_enabled(json_response, data['password']):
+            # we enabled it for the first time
+            changed = True
+        # ...and reset password if needed
+        else:
+            # local auth is enabled but the password differs
+            # we must reset the admin's password
+            password_id = get_admin_password_id()
+
+            if password_id is None:
+                raise ModeError("ERROR: admin's password is set, but we "
+                                + "cannot identify it")
+
+            # TODO
+            raise ModeError("TODO: Reset of the admin password is not yet "
+                            + "implemented")
+
+    if changed:
+        msg = "Local authentication is enabled, admin has assigned password"
+    else:
+        msg = "Local authentication was already enabled, admin's password " \
+            + "is unchanged"
+
+    return changed, msg
+
+
 def mode_settings(api_url, data=None, headers=None, timeout=default_timeout,
                   access_key=None, secret_key=None, dry_run=False):
 
     # check if data contains all required fields
     try:
         if not isinstance(data['option'], str) or data['option'] == '':
-            raise ModeError("ERROR: 'option' must contain a name of the \
-                            option")
+            raise ModeError("ERROR: 'option' must contain a name of the "
+                            + "option")
     except KeyError:
-        raise ModeError("ERROR: Mode 'settings' requires the field: 'option': \
-                        %s" % str(data))
+        raise ModeError("ERROR: Mode 'settings' requires the field: 'option': "
+                        + "%s" % str(data))
     try:
         if not isinstance(data['value'], str) or data['value'] == '':
             raise ModeError("ERROR: 'value' must contain a value")
     except KeyError:
-        raise ModeError("ERROR: Mode 'settings' requires the field: 'value': \
-                        %s" % str(data))
+        raise ModeError("ERROR: Mode 'settings' requires the field: 'value': "
+                        + "%s" % str(data))
 
     # assemble request URL
     request_url = api_url + 'settings/' + data['option'].strip('/')
         raise ModeError(str(e))
 
     if not json_response:
-        raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in the \
-                        response')
+        raise ModeError('ERROR: BAD RESPONSE (GET) - no json value in the '
+                        + 'response')
 
     if is_valid_rancher_api_option(json_response):
         valid = True
             differs, payload = create_rancher_api_payload(json_response,
                                                           data['value'])
         except ValueError:
-            raise ModeError('ERROR: INVALID JSON - missing json values in \
-                            the response')
+            raise ModeError('ERROR: INVALID JSON - missing json values in '
+                            + 'the response')
     else:
         valid = False
 
             raise ModeError(str(e))
 
         if not json_response:
-            raise ModeError('ERROR: BAD RESPONSE (PUT) - no json value in \
-                            the response')
+            raise ModeError('ERROR: BAD RESPONSE (PUT) - no json value in '
+                            + 'the response')
         else:
             changed = True
     else:
                                      secret_key=secret_key,
                                      dry_run=dry_run)
     elif rancher_mode == 'access_control':
-        msg = "SKIP: 'access_control' Not yet implemented"
+        changed, msg = mode_access_control(api_url, data=data,
+                                           headers=http_headers,
+                                           timeout=timeout,
+                                           access_key=access_key,
+                                           secret_key=secret_key,
+                                           dry_run=dry_run)
 
     return changed, msg