Added seed code for access-management.
[ta/access-management.git] / src / access_management / rest-plugin / users_locks.py
1 # Copyright 2019 Nokia
2
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import json
16 from am_api_base import *
17 from keystoneauth1 import exceptions
18 from cmframework.apis import cmclient
19
20
21 class UserLock(AMApiBase):
22
23     """
24     User lock operations
25
26     .. :quickref: User lock;User lock operations
27
28     .. http:post:: /am/v1/users/locks
29
30     **Start User lock**
31
32     **Example request**:
33
34     .. sourcecode:: http
35
36         POST am/v1/users/locks HTTP/1.1
37         Host: haproxyvip:61200
38         Accept: application/json
39         {
40             "user": <uuid> or <username>
41         }
42
43     :> json string user: The locked user's id or name.
44
45     **Example response**:
46
47     .. sourcecode:: http
48
49         HTTP/1.1 200 OK
50         {
51             "code": 0,
52             "description": "User locked success."
53         }
54
55     :> json int code: the status code
56     :> json string description: the error description, present if code is non zero
57
58     User unlock operations
59
60     .. :quickref: User lock;User unlock operations
61
62     .. http:delete:: /am/v1/users/locks
63
64     **Start User unlock**
65
66     **Example request**:
67
68     .. sourcecode:: http
69
70         DELETE am/v1/users/locks HTTP/1.1
71         Host: haproxyvip:61200
72         Accept: application/json
73         {
74             "user": <uuid> or <username>
75         }
76
77     :> json string user: The unlocked user's id or name.
78
79     **Example response**:
80
81     .. sourcecode:: http
82
83         HTTP/1.1 200 OK
84         {
85             "code": 0,
86             "description": "User unlocked!"
87         }
88
89     :> json int code: the status code
90     :> json string description: the error description, present if code is non zero
91     """
92
93     endpoints = ['users/locks']
94     parser_arguments = ['user']
95
96     def post(self):
97         self.logger.info("Received a user lock request!")
98         args = self.parse_args()
99
100         state, user_info = self.get_uuid_and_name(args["user"])
101         if state:
102             status, message = self._lock_user(user_info)
103
104             if status:
105                 self.logger.info("User {0} locked".format(user_info["name"]))
106                 return AMApiBase.embed_data({}, 0, "User locked.")
107             else:
108                 self.logger.error("User {0} lock failed: {1}".format(user_info["name"], message))
109                 return AMApiBase.embed_data({}, 1, message)
110         else:
111             self.logger.error(user_info)
112             return AMApiBase.embed_data({}, 1, user_info)
113
114     def delete(self):
115         self.logger.info("Received a user unlock request!")
116         args = self.parse_args()
117
118         state, user_info = self.get_uuid_and_name(args["user"])
119         if state:
120             status, message = self._unlock_user(user_info)
121
122             if status:
123                 self.logger.info("User {0} unlocked!".format(user_info["name"]))
124                 return AMApiBase.embed_data({}, 0, "User unlocked!")
125             else:
126                 self.logger.error("User {0} unlock failed: {1}".format(user_info["name"], message))
127                 return AMApiBase.embed_data({}, 1, message)
128         else:
129             self.logger.error(user_info)
130             return AMApiBase.embed_data({}, 1, user_info)
131
132     def _unlock_user(self, user_info):
133          try:
134              self.keystone.users.update(user_info["id"], enabled=True)
135          except exceptions.http.NotFound as ex:
136              self.logger.error("{0}".format(ex))
137              return False, "This user does not exist in the keystone!"
138          except Exception as ex:
139              self.logger.error("{0}".format(ex))
140              return False, "{0}".format(ex)
141          return self.user_checker(user_info, "-u")
142
143     def _lock_user(self, user_info):
144         try:
145             self.keystone.users.update(user_info["id"], enabled=False)
146         except exceptions.http.NotFound as ex:
147             self.logger.error("{0}".format(ex))
148             return False, "This user does not exist in the keystone!"
149         except Exception as ex:
150             self.logger.error("{0}".format(ex))
151             return False, "{0}".format(ex)
152         return self.user_checker(user_info, "-l")
153
154     def user_checker(self, user_info, user_state):
155         state_open, message_open = self._open_db()
156         if state_open:
157             try:
158                 roles = self.db.get_user_roles(user_info["id"])
159                 self.logger.debug("Check the chroot role, when locking the user!")
160                 for role in roles:
161                     self.logger.debug("Role name: {0}".format(role))
162                     if self.db.is_chroot_role(role):
163                         self.logger.debug("Found a chroot role attached to the {0} user!".format(user_info["name"]))
164                         self.lock_state_handler(user_info["name"], "Chroot", "cloud.chroot", user_state)
165                     if role == "linux_user":
166                         self.logger.debug("Found a Linux role attached to the {0} user!".format(user_info["name"]))
167                         self.lock_state_handler(user_info["name"], "Linux", "cloud.linuxuser", user_state)
168             except Exception as ex:
169                 self.logger.error("Internal error: {0}".format(ex))
170                 return False, "Internal error: {0}".format(ex)
171             finally:
172                 state_close, message_close = self._close_db()
173                 if not state_close:
174                     self._close_db()
175             return True, ""
176         else:
177             return False, message_open
178
179     def lock_state_handler(self, username, user_type, list_name, state):
180         cmc = cmclient.CMClient()
181         user_list = cmc.get_property(list_name)
182         user_list = json.loads(user_list)
183         self.logger.debug("{0} user list before the change: {1}".format(user_type, json.dumps(user_list)))
184         if user_list is not None:
185             self.logger.debug("The {0} user list exists!".format(user_type))
186             for val in user_list:
187                 if val["name"] == username:
188                     val["lock_state"] = state
189                     break
190             self.logger.debug("{0} user list after the change: {1}".format(user_type, json.dumps(user_list)))
191             cmc.set_property(list_name, json.dumps(user_list))