This feature enable the user to create a SEuser adm based on SElinux adm role and link a LOGIN against it (seisolate: Isolate admin), that way complementing sepolicy adm roles create.
diff --git a/policycoreutils/sepolicy/sepolicy.py b/policycoreutils/sepolicy/sepolicy.py index b25d3b2..0380604 100755 --- a/policycoreutils/sepolicy/sepolicy.py +++ b/policycoreutils/sepolicy/sepolicy.py @@ -446,6 +446,27 @@ def gen_generate_args(parser): help=_("Generate Policy for %s") % poltype[XUSER]) pol.set_defaults(func=generate)
+# Will create a SElinux adm user or (as defined here) a Isolate adm. +def isolateadm(args): + from sepolicy import seisolate + + if args.adminrole and args.login: + seisolate.create_user(args.adminrole, args.login) + seisolate.link(args.adminrole, args.login) + + +def gen_isolateadm_args(parser): + isoadm = parser.add_parser("isolateadm", + help=_("Create a link beteween LOGIN and SEadm user")) + isoadm.add_argument("-a", "--adminrole", dest="adminrole", + action="store", required=True, + help=_("Receive an admin role name")) + isoadm.add_argument("-l", "--login", dest="login", + action="store", required=True, + help=_("Receive a LOGIN to create the SEadm user")) + isoadm.set_defaults(func=isolateadm) + + if __name__ == '__main__': parser = argparse.ArgumentParser(description='SELinux Policy Inspection Tool') subparsers = parser.add_subparsers(help=_("commands")) @@ -459,6 +480,7 @@ if __name__ == '__main__': gen_manpage_args(subparsers) gen_network_args(subparsers) gen_transition_args(subparsers) + gen_isolateadm_args(subparsers)
try: args = parser.parse_args() diff --git a/policycoreutils/sepolicy/sepolicy/seisolate.py b/policycoreutils/sepolicy/sepolicy/seisolate.py index e69de29..f9be58a 100644 --- a/policycoreutils/sepolicy/sepolicy/seisolate.py +++ b/policycoreutils/sepolicy/sepolicy/seisolate.py @@ -0,0 +1,62 @@ +#! /usr/bin/python -Es + +import sys +import seobject +import sepolicy + +from shutil import copy2 +from os import chmod as set_permissions + +# PATH to staff_u that will be base to new users created. +STAFF_U = "staff_u" +COMMON_PATH = "/etc/selinux/targeted/contexts/users/" + +# These are constants used to create SEADM user to a Isolate Admin environment. +SELEVEL = "s0" +PREFIX = "user" +SERANGE = "s0-s0:c0.c1023" + +SUDOERS_PATH = "/etc/sudoers.d/" +SUDOERS_ENTRY = "%s ALL=(ALL) ROLE=%s TYPE=%s ALL" + +# Initialize adm roles list. +ADM_ROLES = [adm_r for adm_r in sepolicy.get_all_roles() if (adm_r[:-2]). + endswith('adm')] +# Initialize a dictionary of se_adm_users with adm_role as key. +ADM_USERS = {key: 'se_'+key[:-2]+'_u' for key in ADM_ROLES} + + +store = "" +__create_user = seobject.seluserRecords(store) +__create_link = seobject.loginRecords(store) + + +def create_user(adm_role, login): + import pwd + try: + pwd.getpwnam(login) + except KeyError: + print("User/Login %s doesn't exist" % login) + sys.exit(1) + + seadm_user = ADM_USERS[adm_role] + roles = "staff_r {role1} {role2}".format(role1=adm_role, + role2="system_r" if adm_role == "sysadm_r" else "") + + if not seadm_user in sepolicy.get_all_users(): + __create_user.add(seadm_user, roles.split(), SELEVEL, + SERANGE, PREFIX) + copy2(COMMON_PATH+STAFF_U, COMMON_PATH+seadm_user) + + +def create_link(adm_role, login): + seadm_user = ADM_USERS[adm_role] + adm_domain = adm_role.replace("_r", "_t") + + if seadm_user in sepolicy.get_all_users(): + __create_link.add(login, seadm_user, SERANGE) + + with open(SUDOERS_PATH+login, 'w') as f: + f.write(SUDOERS_ENTRY % (login, adm_role, adm_domain)) + + set_permissions(SUDOERS_PATH+login, 0440)
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/15/2013 09:49 AM, Leonidas S. Barbosa wrote:
This feature enable the user to create a SEuser adm based on SElinux adm role and link a LOGIN against it (seisolate: Isolate admin), that way complementing sepolicy adm roles create.
Comments inside.
Also need a man page and an update to sepolicy_bash_completion.sh
diff --git a/policycoreutils/sepolicy/sepolicy.py b/policycoreutils/sepolicy/sepolicy.py index b25d3b2..0380604 100755 --- a/policycoreutils/sepolicy/sepolicy.py +++ b/policycoreutils/sepolicy/sepolicy.py @@ -446,6 +446,27 @@ def gen_generate_args(parser): help=_("Generate Policy for %s") % poltype[XUSER]) pol.set_defaults(func=generate)
+# Will create a SElinux adm user or (as defined here) a Isolate adm. +def isolateadm(args): + from sepolicy import seisolate + + if args.adminrole and args.login: + seisolate.create_user(args.adminrole, args.login) + seisolate.link(args.adminrole, args.login) + + +def gen_isolateadm_args(parser): + isoadm = parser.add_parser("isolateadm",
help=_("Create a link beteween LOGIN and
SEadm user"))
No crazy about name.
sepolicy isolateadm
versus
sepolicy admin
Also not sure what the end goal of this is. Do we want this command to be able to just create a mapping between an existing admin role and a login user? Or should it be able to create a new admin rule and connect everything up?
sepolicy admin -l dwalsh -a dbadm_r dbadmin_u
Currently you have
Do we want to allow Add/Modify/Delete?
I think you should allow specification of the command that you will run as root. Default to /bin/bash but allow user to override this.
sepolicy admin -e /bin/myscript -l dwalsh ...
- isoadm.add_argument("-a", "--adminrole", dest="adminrole", +
action="store", required=True, + help=_("Receive an admin role name"))
Should this be the primary key and not require a qualifier? It might be better to use "-r" so I can get -a for add?
- isoadm.add_argument("-l", "--login", dest="login", +
action="store", required=True, + help=_("Receive a LOGIN to create the SEadm user"))
- isoadm.set_defaults(func=isolateadm) + + if __name__ == '__main__':
parser = argparse.ArgumentParser(description='SELinux Policy Inspection Tool') subparsers = parser.add_subparsers(help=_("commands")) @@ -459,6 +480,7 @@ if __name__ == '__main__': gen_manpage_args(subparsers) gen_network_args(subparsers) gen_transition_args(subparsers) + gen_isolateadm_args(subparsers)
try: args = parser.parse_args() diff --git a/policycoreutils/sepolicy/sepolicy/seisolate.py b/policycoreutils/sepolicy/sepolicy/seisolate.py index e69de29..f9be58a 100644 --- a/policycoreutils/sepolicy/sepolicy/seisolate.py +++ b/policycoreutils/sepolicy/sepolicy/seisolate.py @@ -0,0 +1,62 @@ +#! /usr/bin/python -Es + +import sys +import seobject +import sepolicy + +from shutil import copy2 +from os import chmod as set_permissions + +# PATH to staff_u that will be base to new users created. +STAFF_U = "staff_u" +COMMON_PATH = "/etc/selinux/targeted/contexts/users/" +
You should get this from import.selinux Do not want to hard code "targeted", so I can use your tool for other policies.
+# These are constants used to create SEADM user to a Isolate Admin environment. +SELEVEL = "s0" +PREFIX = "user" +SERANGE = "s0-s0:c0.c1023"
Ditto. We need a mechanism to get this from the policy. MLS max is s0-s15:c0.c1023
+SUDOERS_PATH = "/etc/sudoers.d/" +SUDOERS_ENTRY = "%s ALL=(ALL) ROLE=%s TYPE=%s ALL" +
See command above.
SUDOERS_ENTRY = "%s ALL=(ALL) ROLE=%s TYPE=%s %s"
Default -e to be ALL
+# Initialize adm roles list. +ADM_ROLES = [adm_r for adm_r in sepolicy.get_all_roles() if (adm_r[:-2]). + endswith('adm')]
We have got to get this into policy as an attribute. Since this is by convention right now.
+# Initialize a dictionary of se_adm_users with adm_role as key. +ADM_USERS = {key: 'se_'+key[:-2]+'_u' for key in ADM_ROLES} + +
print ADM_USERS {'auditadm_r': 'se_auditadm_u', 'logadm_r': 'se_logadm_u', 'webadm_r': 'se_webadm_u', 'sysadm_r': 'se_sysadm_u', 'secadm_r': 'se_secadm_u', 'dbadm_r': 'se_dbadm_u'}
Is this what you entended?
+store = ""
Should have this passed in from command line.
+__create_user = seobject.seluserRecords(store) +__create_link = seobject.loginRecords(store) + + +def create_user(adm_role, login): + import pwd + try: + pwd.getpwnam(login) + except KeyError: + print("User/Login %s doesn't exist" % login) + sys.exit(1)
Could do this check at the option parsing, but I guess it is alright here.
- seadm_user = ADM_USERS[adm_role] + roles = "staff_r {role1}
{role2}".format(role1=adm_role, + role2="system_r" if adm_role == "sysadm_r" else "") + + if not seadm_user in sepolicy.get_all_users(): + __create_user.add(seadm_user, roles.split(), SELEVEL, + SERANGE, PREFIX) + copy2(COMMON_PATH+STAFF_U, COMMON_PATH+seadm_user) + + +def create_link(adm_role, login): + seadm_user = ADM_USERS[adm_role] + adm_domain = adm_role.replace("_r", "_t") + + if seadm_user in sepolicy.get_all_users(): + __create_link.add(login, seadm_user, SERANGE) + + with open(SUDOERS_PATH+login, 'w') as f: + f.write(SUDOERS_ENTRY % (login, adm_role, adm_domain))
Shouldn't this be for append? Or throw exception if it exists?
set_permissions(SUDOERS_PATH+login, 0440)
-- selinux mailing list selinux@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/selinux
On Tue, Oct 15, 2013 at 11:52:22AM -0400, Daniel J Walsh wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/15/2013 09:49 AM, Leonidas S. Barbosa wrote:
This feature enable the user to create a SEuser adm based on SElinux adm role and link a LOGIN against it (seisolate: Isolate admin), that way complementing sepolicy adm roles create.
Comments inside.
Also need a man page and an update to sepolicy_bash_completion.sh
diff --git a/policycoreutils/sepolicy/sepolicy.py b/policycoreutils/sepolicy/sepolicy.py index b25d3b2..0380604 100755 --- a/policycoreutils/sepolicy/sepolicy.py +++ b/policycoreutils/sepolicy/sepolicy.py @@ -446,6 +446,27 @@ def gen_generate_args(parser): help=_("Generate Policy for %s") % poltype[XUSER]) pol.set_defaults(func=generate)
+# Will create a SElinux adm user or (as defined here) a Isolate adm. +def isolateadm(args): + from sepolicy import seisolate + + if args.adminrole and args.login: + seisolate.create_user(args.adminrole, args.login) + seisolate.link(args.adminrole, args.login) + + +def gen_isolateadm_args(parser): + isoadm = parser.add_parser("isolateadm",
help=_("Create a link beteween LOGIN and
SEadm user"))
No crazy about name.
sepolicy isolateadm
versus
sepolicy admin
Also not sure what the end goal of this is. Do we want this command to be able to just create a mapping between an existing admin role and a login user? Or should it be able to create a new admin rule and connect everything up?
sepolicy admin -l dwalsh -a dbadm_r dbadmin_u
The final goal is to link and use the adm_roles created by sepolicy via generate admin_user (and those adm roles already exists) with UNIX login. So sepolicy admin, create SElinux admin_user based on admin_role and link. Having any login acts as dbadm, logadm, etc.
Not sure if I understood, by a new admin rule you mean a policy .te module that defines this new one?
Currently you have
Do we want to allow Add/Modify/Delete?
Yes.
I think you should allow specification of the command that you will run as root. Default to /bin/bash but allow user to override this.
sepolicy admin -e /bin/myscript -l dwalsh ...
So, commands like chmod, to create a new sudoers.d/file and so on by a extern command, is it?
- isoadm.add_argument("-a", "--adminrole", dest="adminrole", +
action="store", required=True, + help=_("Receive an admin role name"))
Should this be the primary key and not require a qualifier? It might be better to use "-r" so I can get -a for add?
What you call a qualifier? -r seems ok for me.
- isoadm.add_argument("-l", "--login", dest="login", +
action="store", required=True, + help=_("Receive a LOGIN to create the SEadm user"))
- isoadm.set_defaults(func=isolateadm) + + if __name__ == '__main__':
parser = argparse.ArgumentParser(description='SELinux Policy Inspection Tool') subparsers = parser.add_subparsers(help=_("commands")) @@ -459,6 +480,7 @@ if __name__ == '__main__': gen_manpage_args(subparsers) gen_network_args(subparsers) gen_transition_args(subparsers) + gen_isolateadm_args(subparsers)
try: args = parser.parse_args() diff --git a/policycoreutils/sepolicy/sepolicy/seisolate.py b/policycoreutils/sepolicy/sepolicy/seisolate.py index e69de29..f9be58a 100644 --- a/policycoreutils/sepolicy/sepolicy/seisolate.py +++ b/policycoreutils/sepolicy/sepolicy/seisolate.py @@ -0,0 +1,62 @@ +#! /usr/bin/python -Es + +import sys +import seobject +import sepolicy + +from shutil import copy2 +from os import chmod as set_permissions + +# PATH to staff_u that will be base to new users created. +STAFF_U = "staff_u" +COMMON_PATH = "/etc/selinux/targeted/contexts/users/" +
You should get this from import.selinux Do not want to hard code "targeted", so I can use your tool for other policies.
Thanks, fixed.
+# These are constants used to create SEADM user to a Isolate Admin environment. +SELEVEL = "s0" +PREFIX = "user" +SERANGE = "s0-s0:c0.c1023"
Ditto. We need a mechanism to get this from the policy. MLS max is s0-s15:c0.c1023
+SUDOERS_PATH = "/etc/sudoers.d/" +SUDOERS_ENTRY = "%s ALL=(ALL) ROLE=%s TYPE=%s ALL" +
See command above.
SUDOERS_ENTRY = "%s ALL=(ALL) ROLE=%s TYPE=%s %s"
Default -e to be ALL
+# Initialize adm roles list. +ADM_ROLES = [adm_r for adm_r in sepolicy.get_all_roles() if (adm_r[:-2]). + endswith('adm')]
We have got to get this into policy as an attribute. Since this is by convention right now.
Yep, that what I looked for and did not find another way to grab other than that.
+# Initialize a dictionary of se_adm_users with adm_role as key. +ADM_USERS = {key: 'se_'+key[:-2]+'_u' for key in ADM_ROLES} + +
print ADM_USERS {'auditadm_r': 'se_auditadm_u', 'logadm_r': 'se_logadm_u', 'webadm_r': 'se_webadm_u', 'sysadm_r': 'se_sysadm_u', 'secadm_r': 'se_secadm_u', 'dbadm_r': 'se_dbadm_u'}
Is this what you entended?
It was about have always an adm_role associate with its selinux_user, without have to check get_user_list() all the time and string check to see if it already exists.
+store = ""
Should have this passed in from command line.
+__create_user = seobject.seluserRecords(store) +__create_link = seobject.loginRecords(store) + + +def create_user(adm_role, login): + import pwd + try: + pwd.getpwnam(login) + except KeyError: + print("User/Login %s doesn't exist" % login) + sys.exit(1)
Could do this check at the option parsing, but I guess it is alright here.
- seadm_user = ADM_USERS[adm_role] + roles = "staff_r {role1}
{role2}".format(role1=adm_role, + role2="system_r" if adm_role == "sysadm_r" else "") + + if not seadm_user in sepolicy.get_all_users(): + __create_user.add(seadm_user, roles.split(), SELEVEL, + SERANGE, PREFIX) + copy2(COMMON_PATH+STAFF_U, COMMON_PATH+seadm_user) + + +def create_link(adm_role, login): + seadm_user = ADM_USERS[adm_role] + adm_domain = adm_role.replace("_r", "_t") + + if seadm_user in sepolicy.get_all_users(): + __create_link.add(login, seadm_user, SERANGE) + + with open(SUDOERS_PATH+login, 'w') as f: + f.write(SUDOERS_ENTRY % (login, adm_role, adm_domain))
Shouldn't this be for append? Or throw exception if it exists?
I believe just write and throw exception if it exists.
set_permissions(SUDOERS_PATH+login, 0440)
-- selinux mailing list selinux@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/selinux
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iEYEARECAAYFAlJdZLYACgkQrlYvE4MpobMqdACbBQTweM7v2xI4SV1ncZ72TKLJ xvQAn3Yesy7mRhj+FTQ5jniP6UR6xlzp =YXr3 -----END PGP SIGNATURE-----
selinux@lists.fedoraproject.org