Passed
Pull Request — master (#3146)
by Alexander
02:06
created

create_permissions.PermissionGenerator.generate()   F

Complexity

Conditions 26

Size

Total Lines 209
Code Lines 149

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 149
nop 3
dl 0
loc 209
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like create_permissions.PermissionGenerator.generate() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#
2
# create_permission.py
3
#        generate template-based checks for file permissions/ownership
4
5
import re
6
7
from template_common import FilesGenerator, UnknownTargetError
8
9
10
class PermissionGenerator(FilesGenerator):
11
    def generate(self, target, path_info):
12
        # the csv file contains lines that match the following layout:
13
        #    directory,file_name,uid,gid,mode[,preferred_id]
14
15
        dir_path, file_name, uid, gid, mode = path_info[0:5]
16
17
        if uid == "" and gid == "" and mode == "":
18
            # If UID, GID, and mode are not defined, skip processing this file
19
            return
20
21
        # build a string out of the path that is suitable for use in id tags
22
        # example:	/etc/resolv.conf --> _etc_resolv_conf
23
        # path_id maps to FILEID in the template
24
25
        if len(path_info) == 6:
26
            path_id = "_" + path_info[5]
27
        elif file_name == '[NULL]':
28
            path_id = re.sub('[-\./]', '_', dir_path)
29
        elif re.match(r'\^.*\$', file_name, 0):
30
            path_id = re.sub('[-\./]', '_', dir_path) + '_' + re.sub('[-\\\./^$*(){}|]',
31
                                                                     '_', file_name)
32
            # cleaning trailing end multiple underscores, make sure id is lowercase
33
            path_id = re.sub(r'_+', '_', path_id)
34
            path_id = re.sub(r'_$', '', path_id)
35
            path_id = path_id.lower()
36
        else:
37
            path_id = re.sub('[-\./]', '_', dir_path) + '_' + re.sub('[-\./]',
38
                                                                     '_', file_name)
39
            path_id = path_id.lower()
40
41
        # build a string that contains the full path to the file
42
        # full_path maps to FILEPATH in the template
43
        if file_name == '[NULL]':
44
            full_path = dir_path
45
        else:
46
            full_path = dir_path + '/' + file_name
47
48
        if target == "bash":
49
            if not re.match(r'\^.*\$', file_name, 0):
50
                if mode:
51
                    self.file_from_template(
52
                        "./template_BASH_file_permissions",
53
                        {
54
                            "FILEPATH":      full_path,
55
                            "FILEMODE":      mode,
56
                        },
57
                        "./bash/file_permissions{0}.sh", path_id
58
                    )
59
                if uid:
60
                    self.file_from_template(
61
                        "./template_BASH_file_owner",
62
                        {
63
                            "FILEPATH":      full_path,
64
                            "FILEUID":       uid,
65
                        },
66
                        "./bash/file_owner{0}.sh", path_id
67
                    )
68
                if gid:
69
                    self.file_from_template(
70
                        "./template_BASH_file_groupowner",
71
                        {
72
                            "FILEPATH":      full_path,
73
                            "FILEGID":       gid,
74
                        },
75
                        "./bash/file_groupowner{0}.sh", path_id
76
                    )
77
                self.file_from_template(
78
                    "./template_BASH_permissions",
79
                    {
80
                        "FILEPATH":      full_path,
81
                        "FILEMODE":      mode,
82
                        "FILEUID":       uid,
83
                        "FILEGID":       gid,
84
                    },
85
                    "./bash/permissions{0}.sh", path_id
86
                )
87
            else:
88
                file_name = re.sub('^\^', '', file_name)
89
                self.file_from_template(
90
                    "./template_BASH_file_regex_permissions",
91
                    {
92
                        "FILEPATH":      dir_path,
93
                        "FILENAME":      file_name,
94
                        "FILEMODE":      mode,
95
                    },
96
                    "./bash/file_permissions{0}.sh", path_id
97
                )
98
99
        elif target == "ansible" and not re.match(r'\^.*\$', file_name, 0):
100
            if mode:
101
                self.file_from_template(
102
                    "./template_ANSIBLE_file_permissions",
103
                    {
104
                        "FILEPATH":      full_path,
105
                        "FILEMODE":      mode,
106
                    },
107
                    "./ansible/file_permissions{0}.yml", path_id
108
                )
109
            if uid:
110
                self.file_from_template(
111
                    "./template_ANSIBLE_file_owner",
112
                    {
113
                        "FILEPATH":      full_path,
114
                        "FILEUID":       uid,
115
                    },
116
                    "./ansible/file_owner{0}.yml", path_id
117
                )
118
            if gid:
119
                self.file_from_template(
120
                    "./template_ANSIBLE_file_groupowner",
121
                    {
122
                        "FILEPATH":      full_path,
123
                        "FILEGID":       gid,
124
                    },
125
                    "./ansible/file_groupowner{0}.yml", path_id
126
                )
127
128
            self.file_from_template(
129
                "./template_ANSIBLE_permissions",
130
                {
131
                    "FILEPATH":      full_path,
132
                    "FILEMODE":      mode,
133
                    "FILEUID":       uid,
134
                    "FILEGID":       gid,
135
                },
136
                "./ansible/permissions{0}.yml", path_id
137
            )
138
139
        elif target == "oval":
140
            # support pattern matching, requiring that the filename starts with '^'
141
            # and fichishes with '$'
142
            if file_name == '[NULL]':
143
                unix_filename = "<unix:filename xsi:nil=\"true\" />"
144
            elif re.match(r'\^.*\$', file_name, 0):
145
                unix_filename = "<unix:filename operation=\"pattern match\">" + file_name + "</unix:filename>"
146
            else:
147
                unix_filename = "<unix:filename>" + file_name + "</unix:filename>"
148
149
            unix_dir = "<unix:path>" + dir_path + "</unix:path>"
150
151
            # we are ready to create the check
152
            # open the template and perform the conversions
153
            if mode:
154
                # build the state that describes our mode
155
                # mode_str maps to STATEMODE in the template
156
                fields = ['oexec', 'owrite', 'oread', 'gexec', 'gwrite', 'gread',
157
                          'uexec', 'uwrite', 'uread', 'sticky', 'sgid', 'suid']
158
                mode_int = int(mode, 8)
159
                mode_str = ""
160
                for field in fields:
161
                    if mode_int & 0x01 == 1:
162
                        mode_str = "	<unix:" + field + " datatype=\"boolean\">true</unix:" + field + ">\n" + mode_str
163
                    else:
164
                        mode_str = "	<unix:" + field + " datatype=\"boolean\">false</unix:" + field + ">\n" + mode_str
165
                    mode_int = mode_int >> 1
166
167
                self.file_from_template(
168
                    "./template_OVAL_file_permissions",
169
                    {
170
                        "FILEID":        path_id,
171
                        "FILEPATH":      full_path,
172
                        "FILEMODE":      mode,
173
                        "STATEMODE":     mode_str,
174
                        "UNIX_DIR":      unix_dir,
175
                        "UNIX_FILENAME": unix_filename
176
                    },
177
                    "./oval/file_permissions{0}.xml", path_id
178
                )
179
            if uid:
180
                self.file_from_template(
181
                    "./template_OVAL_file_owner",
182
                    {
183
                        "FILEID":        path_id,
184
                        "FILEPATH":      full_path,
185
                        "FILEUID":       uid,
186
                        "UNIX_DIR":      unix_dir,
187
                        "UNIX_FILENAME": unix_filename
188
                    },
189
                    "./oval/file_owner{0}.xml", path_id
190
                )
191
            if gid:
192
                self.file_from_template(
193
                    "./template_OVAL_file_groupowner",
194
                    {
195
                        "FILEID":        path_id,
196
                        "FILEPATH":      full_path,
197
                        "FILEGID":       gid,
198
                        "UNIX_DIR":      unix_dir,
199
                        "UNIX_FILENAME": unix_filename
200
                    },
201
                    "./oval/file_groupowner{0}.xml", path_id
202
                )
203
            self.file_from_template(
204
                "./template_OVAL_permissions",
205
                {
206
                    "FILEID":        path_id,
207
                    "FILEPATH":      full_path,
208
                    "FILEDIR":       dir_path,
209
                    "FILEMODE":      mode,
210
                    "FILEUID":       uid,
211
                    "FILEGID":       gid,
212
                    "UNIX_DIR":      unix_dir,
213
                    "UNIX_FILENAME": unix_filename
214
                },
215
                "./oval/permissions{0}.xml", path_id
216
            )
217
218
        else:
219
            raise UnknownTargetError(target)
220
221
    def csv_format(self):
222
        return("CSV should contains lines of the format: "
223
               "directory path,file name,owner uid (numeric),group "
224
               "owner gid (numeric),mode[,preferred_id]")
225