When evaluating the profile-based policy, the policy server must first determine which of the profiles match the incoming request. The policy uses the Who, What, Where, and When criteria specified in the profiles to determine a match. Note that the filename used for the profile is significant. The policy checks each of the profiles sequentially, in lexical order until a match is found. Once the a profile is selected, the remaining profiles are not evaluated.
Privilege Manager for Unix profiles (or roles) define who, what, where, when, and how users are permitted to perform various privileged account actions using variable values in the policy configuration profiles.
The following tables list the predefined variables used in profile-based policy.
Table 9: General variables
General |
pf_profile |
String |
The profile name. This variable is set by the profileBasedPolicy.conf file to be the base filename of the profile, minus the .profile or .shellprofile extension. |
pf_profiledescription |
String |
A description of the profile.
EXAMPLE:
pf_profiledescription = "This is a description of this profile." |
pf_enableprofile |
Boolean |
Set to true to enable the profile.
EXAMPLE:
pf_enableprofile = true; |
pf_tracelevel |
Number |
Enables tracing/debugging output at different levels:
- 1: show reason for reject
- 2: verbose output
- 3: show debug trace
EXAMPLE:
pf_tracelevel = 1; |
pf_enablekeystrokelogging |
Boolean |
Set to true to enable keystroke logging.
EXAMPLE:
pf_enablekeystrokelogging = true; |
pf_iologdir |
String |
The directory in which to store I/O logs. A unique file is created in this directory for each keystroke logging session.
EXAMPLE:
pf_iologdir = "/var/opt/quest/qpm4u/iolog/"; |
pf_logpasswords |
Boolean |
Set to false to avoid writing passwords to the keystroke log. The password detection is determined by the pf_passprompts list.
EXAMPLE:
pf_logpasswords = false; |
pf_passprompts |
List |
A list of strings interpreted as password prompts in stdout.
EXAMPLE:
pf_passprompts = {"[pP]assword[ :]*"}; |
Authentication |
pf_enableauthentication |
Boolean |
Set to true to enable PAM authentication. By default, the submit user is authenticated on the master host using the sshd service.
EXAMPLE:
pf_enableauthentication = true; |
pf_authenticateonclient |
Boolean |
Set to true to require authentication on the client. If set to false, users are authenticated on the server, not on the client.
EXAMPLE:
pf_authenticateonclient = true;
Authentication is only required if pf_enableauthentication = true. |
pf_pamservice |
String |
Identifies the PAM service to use when authenticating to PAM.
EXAMPLE:
pf_pamservice = "sshd"; |
pf_pam_prompt |
String |
Configures the prompt to use with PAM.
EXAMPLE:
pf_pam_prompt = "Password: "; |
pf_allowscp |
|
Set to true to allow scp and non-interactive SSH commands when authentication for the shell is enabled.
Only applies to pmksh, pmcsh, pmsh, pmbash, and pmshellwrapper.
EXAMPLE:
pf_allowscp = false; |
Table 10: What settings
Commands |
pf_authpaths |
List |
Specifies the paths from which commands are permitted to run. Empty lists are ignored. If not empty, this variable is passed to the agent for authorization at the point where the command is about to be run; the agent will then reject a command unless it is run from one of these paths.
For a shell profile, this restriction is applied to the shell program itself, and to commands run from within the shell.
EXAMPLE:
pf_authpaths = {
# no path restrictions
}; |
pf_authcmds |
List |
Commands authorized to run; commands not in the list are rejected.
Considerations:
- If you specify a fully qualified path in pf_authcmds, you must specify the fully qualified path in the requested command.
- glob is used to match the path, so be careful when using wild cards in the path.
- You can precede an entry with an optional NOEXEC flag to ensure that the run command is blocked from forking any child processes. Put the flag at the beginning of the string and enclose the flag with '[]'.
EXAMPLE:
pf_authcmds = {
"/usr/bin/id *"
}; |
pf_enableremotecmds |
Boolean |
Set to true to allow commands to run on a different host when running pmrun with the -h option .
EXAMPLE:
pf_enableremotecmds = false; |
Shell commands |
pf_shellcommandsaccept |
List |
Specifies the list of commands accepted by pmmasterd when run from within the shell. pmmasterd authorizes listed commands and they produce an event in the audit log. If pf_shellcommandsaccept is not empty, any matching command is accepted; all others are rejected.
Considerations:
- Only configure pf_shellcommandsreject or pf_shellcommandsaccept.
- If both lists are empty, then all commands are accepted.
- Only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellcommandsaccept = {
}; |
pf_shellcommandsreject |
List |
Specifies the list of commands rejected by pmmasterd when run from within the shell. pmmasterd authorizes listed commands and they produce an event in the audit log. If pf_shellcommandsreject is not empty, any matching command is be rejected; all others are accepted.
Considerations:
- Only configure pf_shellcommandsreject or pf_shellcommandsaccept.
- If both lists are empty, then all commands are accepted.
- Only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellcommandsreject = {
}; |
pf_checkbuiltins |
Boolean |
Set to true to use shell builtins just like commands.
This only applies to pmksh, pmcsh, and pmsh.
EXAMPLE:
pf_checkbuiltins = true; |
pf_shellreject |
String |
Message to display when a user attempts to run a forbidden command.
This only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellreject = "You are not permitted to run this command"; |
Pre-authorized Commands |
pf_shellallow |
List |
Defines the list of pre-authorized commands allowed by the shell without further authorization by the master. The shell interprets each item in this list as a regular expression. Listed commands do not result in an audit event in the event log.
This only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellallow = {
"(^|/)(exit|pwd|echo)$",
}; |
pf_shellallowpipe |
List |
Defines the list of pre-authorized commands allowed by the shell without further authorization by the master, but only in the case where std input is from a pipe (for example, ls | more). The shell interprets each item in this list as a regular expression. Listed commands do not result in an audit event in the eventlog.
This only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellallowpipe = {
"(^|/)(awk|more|grep)$",
# allow pipe to innocuous common commands
}; |
pf_shell_forbid |
List |
Defines the list of commands rejected by the shell without further authorization by the master. The shell interprets each item in this list as a regular expression. Listed commands do not result in an audit event in the event log.
This only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellforbid = {
"(^|/)(passwd|kill|shutdown)$",
# forbid sensitive commands
"(^|/)(a|b|c|k|z)?sh$",
# forbid normal shells
"(^|/)(bash|tcsh)$",
# forbid normal shells
"(^|/)nc$",
# forbid cmds that allow remote execution
}; |
Table 11: Where settings
Run Hosts |
pf_authrunhosts |
List |
Hosts where commands can run. If not empty, you can submit commands from any host in this list.
EXAMPLES:
pf_authsubmithosts = {"host1"};
# allow cmds from host host1 only
pf_authsubmithosts = {"*.one.two"};
# allow cmds from *.one.two only
pf_authsubmithosts = {ALL};
# allow cmds from all hosts
SAFEHOSTS = {"*.one.two"};
pf_authsubmithosts = {SAFEHOSTS};
# allow cmds from *.one.two only |
pf_authrunhostsad |
List |
Active Directory host groups where commands can run. If not empty, you can submit commands from any host in this list. You can specify an Active Directory domain name as part of the arguments; for example, as <domain>/<name>, <domain>\\<name>, or <name>. If a domain is not specified, then it uses the default joined domain.
These lists do not support wild cards.
EXAMPLES:
pf_authrunhostsad = { "TESTDOM1/testhosts1", "TESTDOM2/dbhosts1"};
# match any member of either AD group
pf_authrunhostsad = { "testhosts1" };
# match members in the specified AD group in the default joined domain
pf_authrunhostsad = {
};
# match no AD groups |
Submit Hosts |
pf_authsubmithosts |
List |
Hosts where commands can be submitted. If not empty, you can submit commands from any host in this list.
EXAMPLES:
pf_authsubmithosts = {"host1"};
# allow cmds from host host1 only
pf_authsubmithosts = {"*.one.two"};
# allow cmds from *.one.two only
pf_authsubmithosts = {ALL};
# allow cmds from all hosts
SAFEHOSTS = {"*.one.two"};
pf_authsubmithosts = {SAFEHOSTS};
# allow cmds from *.one.two only |
pf_authsubmithostsad |
List |
Active Directory host groups where commands can be submitted. If not empty, you can submit commands from any host in this list. You can specify a domain name as part of the arguments; for example, as <domain>/<name>, <domain>\\<name>, or <name>. If a domain is not specified, then it uses the default joined domain.
These lists do not support wild cards.
EXAMPLES:
pf_authsubmithostsad = { "TESTDOM1/testhosts1", "TESTDOM2/dbhosts1"};
# match any member of either AD group
pf_authsubmithostsad = { "testhosts1" };
# match members in the specified AD group
# in the default joined domain
pf_authsubmithostsad = {
};
# match no AD groups |
Forbidden Run Hosts |
pf_forbidrunhosts |
List |
Hosts where members are forbidden to run commands. If not empty, you can submit commands from any host NOT in this list.
EXAMPLES:
pf_forbidrunhosts = {"fred"}; i
# allow cmds to all hosts except fred
pf_forbidrunhosts = {"*.one.two"};
# allow cmds to all hosts except *.one.two
BADHOSTS = {"*.one.two"};
pf_forbidrunhosts = {BADHOSTS};
# allow cmds to all hosts except *.one.two |
pf_forbidrunhostsad |
List |
Active Directory host groups where members are forbidden to run commands. If not empty, you can submit commands from any host NOT in this list. You can specify a domain name as part of the arguments; for example, as <domain>/<name>, <domain>\\<name>, or <name>. If a domain is not specified, then it uses the default joined domain.
These lists do not support wild cards.
EXAMPLES:
pf_forbidrunhostsad = { "TESTDOM1/testhosts1", "TESTDOM2/dbhosts1"};
# match any member of either AD group
pf_forbidrunhostsad = { "testhosts1" };
# match members in the specified AD group in the default joined domain
pf_forbidrunhostsad = { };
# match no AD groups |
Forbidden Submit Hosts |
pf_forbidsubmithosts |
List |
Hosts where members are forbidden to submit commands. If not empty, you can submit commands from any host NOT in this list.
EXAMPLES:
pf_forbidsubmithosts = {"host1"};
# allow cmds from all hosts except host1
pf_forbidsubmithosts = {"*.one.two"};
# allow cmds from all hosts except *.one.two
BADHOSTS = {"*.one.two"};
pf_forbidsubmithosts = {BADHOSTS};
# allow cmds from all hosts except *.one.two |
pf_forbidrunhostsad |
List |
Active Directory host groups where members are forbidden to submit commands. If not empty, you can submit commands from any host NOT in this list. You can specify a domain name as part of the arguments; for example, as <domain>/<name>, <domain>\\<name>, or <name>. If a domain is not specified, then it uses the default joined domain.
These lists do not support wild cards.
EXAMPLES:
pf_forbidrunhostsad = { "TESTDOM1/testhosts1", "TESTDOM2/dbhosts1"};
# match any member of either AD group
pf_forbidrunhostsad = { "testhosts1" };
# match members in the specified AD group in the default joined domain
pf_forbidrunhostsad = { };
# match no AD groups |
If a member (a user for the group lists, or a host for the hosts lists) is found in both forbid and auth lists, the request is rejected; the forbid list takes precedence.
Table 12: Who settings
Users |
pf_authusers |
List |
Identifies the list of users that match this profile.
EXAMPLES:
pf_authusers = {
};
# No users assigned to this profile
pf_authusers = { "jsmith", "dbrown"};
# match either user
pf_authusers = { ALL};
# match all users
DBUSERS={"TESTDOM1/fred", "TESTDOM2/john"};
# allow cmds from /bin,/usr/bin,/tmp
pf_authusers = { "jsmith*", DBUSERS};
# match fred, john & jsmith* |
pf_authuser |
String |
Identifies the runas user.
EXAMPLE:
pf_authuser = user;
The runas user can be:
- Any valid user name on the agent, such as:
pf_authuser = "fred";
# run command as fred
- A user variable or empty string ("") to run the command as the submit user; that is, set runuser=user (the default)
pf_authuser = user;
# run command as submit user
pf_authuser = "";
# run command as submit user
- The requestuser variable to run the command as the user selected using the pmrun -u user option.
pf_authuser = requestuser;
# run command as the requested user |
Groups |
pf_authgroups |
List |
You can assign users to this profile by group membership on the client or server host, or by assigning individual user names. By default the group membership is verified against the submit user's group information passed on from the client host by pmrun. You can configure it to verify the group membership on the master host instead, using the pf_useservergroupinfo variable.
EXAMPLES:
pf_authgroups = { "admins", "dbas"};
# match any member of either group
pf_authgroups = { ALL};
# match all groups
DBGROUPS = {"db*"};
pf_authgroups = { DBGROUPS, "root"};
# match all db* groups and root |
pf_authgroup |
String |
If accepted, the request runs with the specified group as the rungroup.
EXAMPLE:
pf_authgroup = use_rungroup;
The rungroup can be:
- Any valid group name on the agent, such as:
pf_authgroup ="fred";
# run command as group fred
- A group variable or empty string ("") to run the command as the submit group; that is, set rungroup=group (the default)
pf_authgroup = group;
# run command as submit group
pf_authgroup = "";
# run command as submit group
- The use_rungroup constant to defer setting the rungroup to pmlocald; pmlocald will obtain the runuser's primary group and use that.
pf_authgroup = use_rungroup;
# run command as runuser's group on the agent |
pf_useservergroupinfo |
Boolean |
Set to true to check that the user is a member of one of the pf_authgroups on the master host, otherwise check the user's group membership on the client host.
EXAMPLE:
pf_useservergroupinfo = false; |
AD Groups |
pf_authgroupsad |
List |
Identifies the list of non Unix-enabled AD groups that match this profile. Use the format: <domain>/<name, <domain>\\<name>, or <name>. If you do not specify the domain, it uses the default joined domain.
This list does not support wild cards.
EXAMPLES:
pf_authgroupsad = { "TESTDOM1/testgroup1", "TESTDOM2/dbgroup1"};
# match any member of either AD group
pf_authgroupsad = { };
# match no AD groups |
Table 13: When settings
Time Restrictions |
pf_enabletimerestrictions |
Boolean |
Set to true to enforce the time restrictions in the restrictionHours list.
EXAMPLE:
pf_enabletimerestrictions = true; |
pf_restrictionhours |
List |
Start and End time of allowed time period. Set to "*" or empty string to disable time restrictions. Use 24-hour format, with no leading zero.
EXAMPLES:
pf_restrictionhours = {"8:00", "18:00};
# 8am - 8pm
pf_restrictionhours = {"22:00", "07:00};
# 10pm - 7am
pf_restrictionhours = {"", ""};
# no restrictions
pf_restrictionhours = {"*", "*"};
# no restrictions |
pf_restrictiondates |
List |
Configures the actual date restrictions applied if pf_enabletimerestrictions is set to true. Specify Start and End dates using yyyy/mm/dd format.
EXAMPLES:
pf_restrictiondates = {"2012/01/01", ""};
# no expiry
pf_restrictiondates = {"", "2012/01/01"};
# no start date
pf_restrictiondates = {"2012/01/01", "2012/12/31"};
# check start and end date
pf_restrictiondates = {"", ""};
# no restrictions
pf_restrictiondates = {"*", "*"};
# no restrictions |
pf_restrictiondow |
List |
Configures the day of the week restrictions applied if pf_enabletimerestrictions is set to true. Specify Days in any order using the lower case 3-letter abbreviation {"fri","sat","sun","mon","tue","wed","thu"};
EXAMPLES:
pf_restrictiondow = {"mon","tue","wed","thu","fri"};
# weekdays only
pf_restrictiondow = {"fri","sat","sun","mon","tue","wed","thu"};
# all days
pf_restrictiondow = {};
# no restrictions |
Table 14: How settings
Shell Settings |
pf_allowshells |
List |
List of allowed shells. Do not specify full paths. This list is not compared with the runcommand, instead it is compared with the special pmshell_prog variable set by a Privilege Manager for Unix shell.
Only applies to pmksh, pmcsh, pmsh, pmbash, and pmshellwrapper.
EXAMPLE:
pf_allowshells ={"pmksh", "pmcsh", "pmsh", "pmshellwrapper"}; |
pf_restricted |
Boolean |
Set to true to run the shell in restricted mode.
This means:
- user cannot change directory
- user cannot change PATH, ENV, SHELL
- user can only run programs in PATH
- no absolute/relative paths allowed
- user cannot use io redirection with the '>' or '<' characters
Only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_restricted = true; |
pf_shellreadonly |
List |
List of environment variables to treat as read-only. In restricted mode, the PATH, ENV, and SHELL variables are always read-only.
Only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellreadonly = {}; |
pf_shellcwd |
Sting |
Defines the initial directory where the shell program will be run. The default is to use the runuser's home directory. This is particularly relevant for shells running in restricted mode, where the user cannot change the directory.
This only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellcwd = use_rundir; |
pf_shellpath |
String |
Defines the PATH that will be applied for the shell session. The default is to set standard paths, and add the runuser's home directory, and the current directory. This is particularly relevant for shells running in restricted mode, where the user cannot change the PATH, and can only run commands relative to the configured PATH.
This only applies to pmksh, pmcsh, pmsh, and pmbash.
EXAMPLE:
pf_shellpath = {
"/usr/bin",
"/bin",
use_rundir,
".",
}; |
To understand what happens when the Privilege Manager for Unix policy server receives a request, let's assume the default profile-based policy (pmpolicy) has been configured and user jbloggs issued a pmrun id command from host qpmhost01.
A pmmasterd process on the policy server receives the request, and pmrun sends it details about the request which are recorded as event variables (for example, user="jbloggs", command="id", submithost="qpmhost01", runhost="qpmhost01", date="2013/01/01", time="15:00:00").
With instructions from the code in profileBasedPolicy.conf, pmmasterd looks through each of the profiles until it finds a match between the profile variables (such as, pf_authusers) and the corresponding variables from the request (such as, user).
Note that pmshell and pmshellwrapper requests (such as, pmksh or pmshellwrapper_bash), the code directs pmmasterd to look through the shell profiles instead.
The default profile-based policy (pmpolicy) comes with four profiles: admin, demo, helpdesk, and webadmin.
- The admin profile is skipped because its pf_authusers lists only includes the root user.
- The helpdesk and webadmin profiles are disabled because their pf_enableprofile variables are set to false.
- This only leaves the demo profile, which is listed below.
################################################################################
# Privilege Manager for Unix Profile: demo
#
# This profile permits any user from any host to submit the "id" and "whoami" commands
# to be executed as the root user on the local host.
################################################################################
pf_profiledescription= "Permit root access to id and whoami for demo purposes";
# Enable profile
pf_enableprofile= true;
# Enable Keystroke Logging
pf_enablekeystrokelogging= true;
# No authentication required
pf_enableauthentication= false;
# Apply time restrictions
pf_enabletimerestrictions= true;
# Only permit execution between 7am and 7pm
pf_restrictionhours= {"7:00","19:00"};
# No date restrictions
pf_restrictiondates= {"",""};
# Do not permit user to run remotely using pmrun -h
pf_enableremotecmds= false;
# Run these commands as root user
pf_authuser= "root";
# Run these commands as root's primary group on runhost
pf_authgroup= use_rungroup;
################################################################################
# Profile Membership
################################################################################
# Allow all users to run these commands
pf_authusers={
ALL
};
# allow session to be requested from any host
pf_authsubmithosts={
ALL,
};
# allow session to run on any host
pf_authrunhosts={
ALL,
};
# Only permit commands if run from /usr/bin or /bin
pf_authpaths={
"/usr/bin",
"/bin",
};
# permit id with any number of args (or none)
# permit whoami, only if run with no args
pf_authcmds={
"id **",
"whoami",
};
The demo profile is selected because the who, what, where, and when criteria match the request.
Table 15: Matching the request to the demo profile
Who |
pf_authusers={ALL}; |
user="jbloggs" |
Yes |
What |
pf_authcmds= {"id **", "whoami"}; pf_authpaths= {"/usr/bin","/bin"); |
command="id"
(n/a, path validated by pmlocald) |
Yes |
Where |
pf_authsubmithosts={ALL}; pf_autrunhosts={ALL}; |
submithost="qpmhost01" runhost="qpmhost01" |
Yes |
When |
pf_restrictionhours= {"07:00:00","19:00:00}; |
time="15:00:00" |
Yes |
The policy is not able to validate the command path against pf_authpaths, since an absolute path to the command was not provided with the request. Because of this, pmmasterd accepts the request without checking the path, and leaves pf_authpaths to be validated by the pmlocald.
Once the policy selects a profile, other profile variables may affect how requests are processed. For example, pf_enableauthentication specifies whether password authentication is required.
If the root user issued the same pmrun request, the admin profile would have been selected. Even though both the admin and demo profiles match the request, the admin profile matches first.
The default profile-based policy (pmpolicy) includes a profile_customer_policy.conf file, which you may edit to include customized policy code. This policy file defines the following stub functions and procedures that allow your custom code to run at specific points during the policy evaluation.
fn_customer_init()
This function is called once per policy evaluation, at the start of the policy's main body (located near the end of the profileBasedPolicy.conf file), just after the policy includes the profile_customer_policy.conf file.
fn_custom_profile_init()
This function is called after matching the user or group to a profile (or shell profile) but before checking anything else. You can find the function in procedure pr_processProfile() in the profileBasedPolicy.conf file.
This function can cause the current profile selection to fail by returning a false value.
pr_custom_profile_reset()
Use this procedure to reset custom profile variables added to the profile_customer_policy.conf file. This procedure is called when the profile match fails.
fn_log_and_accept_custom()
This function is called just before the request is accepted, after the request has been successfully matched to a profile. The function is called from the fn_log_and_accept() function in the profileBaseProfile.conf file.