From e761503f11f5076bfbf88a427d470beac65fcd08 Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Thu, 30 Sep 2021 11:00:10 +0300 Subject: [PATCH 01/16] Password Hardening HLD --- doc/passw_hardening/chage.JPG | Bin 0 -> 23269 bytes doc/passw_hardening/hld_password_hardening.md | 670 ++++++++++++++++++ .../passh_arc_sonic.drawio.png | Bin 0 -> 27848 bytes doc/passw_hardening/ph_diagram.jpg | Bin 0 -> 30903 bytes 4 files changed, 670 insertions(+) create mode 100644 doc/passw_hardening/chage.JPG create mode 100644 doc/passw_hardening/hld_password_hardening.md create mode 100644 doc/passw_hardening/passh_arc_sonic.drawio.png create mode 100644 doc/passw_hardening/ph_diagram.jpg diff --git a/doc/passw_hardening/chage.JPG b/doc/passw_hardening/chage.JPG new file mode 100644 index 0000000000000000000000000000000000000000..43ea4159fd65a1cd1ccb463c94718abc50aa23a3 GIT binary patch literal 23269 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 kP4=LI3%jsjG!WkUo1EY1{Fa^HE9Table of Content +* 1. [Table of Content](#TableofContent) + * 1.1. [Revision](#Revision) + * 1.2. [Scope](#Scope) + * 1.3. [Definitions/Abbreviations](#DefinitionsAbbreviations) + * 1.4. [Overview](#Overview) + * 1.5. [Requirements](#Requirements) + * 1.6. [Architecture Design](#ArchitectureDesign) + * 1.7. [High-Level Design](#High-LevelDesign) + * 1.7.1. [Flow description:](#Flowdescription:) + * 1.7.2. [Password Hardening Constrains](#PasswordHardeningConstrains) + * 1.8. [SAI API](#SAIAPI) + * 1.9. [Configuration and management](#Configurationandmanagement) + * 1.9.1. [CLI/YANG model Enhancements](#CLIYANGmodelEnhancements) + * 1.9.2. [Config DB Enhancements](#ConfigDBEnhancements) + * 1.9.3. [Secure Password Table Schema](#SecurePasswordTableSchema) + * 1.10. [3rd Party Components](#rdPartyComponents) + * 1.10.1. [pam-cracklib](#pam-cracklib) + * 1.10.2. [PW Age](#PWAge) + * 1.10.3. [PW History](#PWHistory) + * 1.11. [Warmboot and Fastboot Design Impact](#WarmbootandFastbootDesignImpact) + * 1.12. [Restrictions/Limitations](#RestrictionsLimitations) + * 1.13. [Test Plan](#TestPlan) + * 1.13.1. [Setups](#Setups) + * 1.13.2. [CLI configurational tests](#CLIconfigurationaltests) + * 1.13.3. [Precondition:](#Precondition:) + * 1.13.4. [Case 3: check secure password age (expiration) and warning configuration](#Case3:checksecurepasswordageexpirationandwarningconfiguration) + * 1.13.5. [Case 4 – sanity test](#Case4sanitytest) + * 1.13.6. [Negative cases](#Negativecases) + * 1.13.7. [Case 1: check basic configuration – bad flow with invalid input](#Case1:checkbasicconfigurationbadflowwithinvalidinput) + * 1.13.8. [Test Open Issues](#TestOpenIssues) + + +### 1.1. Revision +Rev 0.1 +### 1.2. Scope + + This password hardening hld doc described the requirements, arcquitecture and configuration details of password hardening feature in switches Sonic OS based. + +### 1.3. Definitions/Abbreviations + PW - password + SPASSWD - secure password daemon + +### 1.4. Overview + + Password Hardening, a user password is the key credential used in order to verify the user accessing the switch and acts as the first line of defense in regards of securing the switch. + The complexity of the password, it's replacement capabilities and change frequency define the security level of the first perimeter of the switch. + Therefore - in order to further improve and harden the switch - a secure mechanism is required to enforce PW policies. + +### 1.5. Requirements +| Requirement | Capabilities | Config Parameters | Notes +| ------ | ------| ------ | ------ | +| PW Length | The PW length should have a minimum length requirement

The PW length should have a maximum length requirement| The user should be able to configure the minimum PW length

The user should be able to configure the maximum PW length | Min PW length is between 0 to 32 chars (default 8)

Max PW length is between 64 to 80 chars (default 64) +| PW Aging | The PW should have an expiration date, after which the user is required to change the PW

A warning to change the PW should be presented to the user a fixed time before the expiration date arrives. This warning should appear in every login so long as the PW expiration time <= warning time. |The user should be able to configure the expiration time of the PW. The user will be able to configure "no aging" for the PW

The user should be able to configure the amount of days to present the warning before the PW expires | PW age time is to be between 1 to 365 days (default 180)

PW warning show is to be between 1 to 30 days (default 15) +| PW constraints | The PW class represents the possible characters comprising the PW. There are 4 character classes that can make up the PW:small characters, big characters, numbers and special chars presented on a standard keyboard

The account name and PW need to be different

The new PW is to be different from current PW|The user should be able to define which characters classes are required for the PW out of the 4 provided



The user will be able to enable or disable this feature|Legal special characters `~!@#$%^&*()-_=+\|[{}];:',<.>/? and white space



An error will be shown to the user if it tries to set the same PW as the username



default - enable + +### 1.6. Architecture Design +Arc design diagram\ +![passh_arc_sonic](passh_arc_sonic.drawio.png) + +(flow description in the chapter below) + +### 1.7. High-Level Design + + In this section we will present the design (as thorough as possible) for the secure PW implementation. + + User password as explained before is the first line defence, in order to support it according the requirement section and user preferences, the secure password feature need a strengh-checking for password. + + The feature will use 3 linux libs: pam-cracklib, chage and pam_pwhistory.so + + pam-cracklib: This module can be plugged into the password stack of a given application to provide some plug-in strength-checking for passwords. + + The action of this module is to prompt the user for a password and check its strength against a system dictionary and a set of rules for identifying poor choices. + This module support many options, including the requirements of PW Length & PW constraints. (see option strengh-checking below) + + chage: support the requirement of PW Aging, change user password expiry information + + pam_pwhistory - PAM module to remember last passwords + + Note: + See linux 3d party component chapter for more description + + +##### Flow diagram: + +![password hardening flow](ph_diagram.jpg) + +#### 1.7.1. Flow description: + Users by using Switch CLI will set new password/password configuration (see PW options below), the input will be saved in CONF_DB in PASSW_CONF_TABLE.\ + The daemon call PASSHD (password hardening daemon) listen to changes, parse the inputs and set the configuration to kernel by using pam-cracklib ,chage, pwhistory linux libs. + After that, it will save the configuration and results in APPL_DB in PASSW_CONF_TABLE. + + Note: + The table PASSW_CONF_TABLE should reduce time consuming when users need to read configuration, because it will avoid to make additional calls to kernel. + +#### 1.7.2. Password Hardening Constrains + The PW Hardening features will be support different options by encapsulate cracklib, chage and pwhistory options according the constrains definitions below. + +##### PW enable + + Enable/Disable password hardening feature + + Note: when this feature is disable will be just the default password validation without strength-checking for passwords. + +##### PW Class + PW class is the type of characters the user is required to enter when setting/updating a PW. + + There are 4 classes: + + Small characters - a-z + + Big characters - A-Z + + Numbers - 0-9 + + Special Characters `~!@#$%^&*()-_+=\|[{}];:',<.>/? and white space + + Each of these classes will receive a Regexp to represent the class. + + The user will be able to choose whether to enforce all PW class characters in the PW or only a subset of the characters. + + Note: + In order to implement it, the daemon will encapsulate some pam-cracklib options. + i.e: + + To request at least one character of every class, the PASSWD daemon will set: + pam-cracklib options: lcredit=-1, ucredit=-1, dcredit=-1. + (meaning that the user need at least one character of the types.) + +##### PW Length + PW length is a base requirement for the PW. + + All password length enforcements and changes will be applied the next time the user would require a PW change or would want to change his own password + +* Minimum Length + + The minimum length of the PW should be subject to a user change. + + The user will be able to change the password minimum length if he has the necessary permissions to change the PW. The CLI command to change the PW: + + + +Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change + +##### PW Age + Along with every PW set to a user, attached to it is the age of the PW - the amount of time that has passed since a PW change has occurred. + + This PW change can either be from the initial config wizard or from the CLI. + +* PW Age Change + Once a PW change takes place - the DB record for said PW is updated with the new PW value and a fresh new age (=0). + + Every login (and PW entry) will check the PW age field to see if it has exceeded its maximum time alive (the amount of time before the PW needs to change). + + If so - a prompt will be shown to the user forcing it to change the PW before logging into the switch. Prompt PW change view will be explained in TBD. + + To support it, can be use chage lib option "--maxdays" + +* PW Age Change Warning + The switch will provide a warning for PW change beforehand (this is to allow a sufficient warning for upgrading the PW which might by relevant to numerous switches). + + Along with this warning - the user will also be able to control how long before the PW expiration this warning will appear. + + To support it, can be use chage option "--warndays" + +Notes: +For implement the "aging" we need to change the /etc/login.def file and set max days and warning days, this changes affection globally, meaning all new users. +For read the information per user we will use the "chage" library. +In addition, when we change the file /etc/login.def its change globally by only new users, so basically for change existing users expired day we need to iterate every one of them using the "chage" lib. + + +##### PW username-match +By enabling this feature, the user will not be permitted to set the same username & password + + +##### PW Saving +Saved previous passwords in the DB, for enable this. is necessary to set how many old password you would like to save. + +Note: will be support by using pam_pwhistory.so, remmember=N option. +For saving password with sha512, need to modify the /etc/pam.d/system-auth-a file to contain this line: + + password sufficient pam_unix.so sha512 shadow use_authtok + +### 1.8. SAI API + no changed. + +### 1.9. Configuration and management + +#### 1.9.1. CLI/YANG model Enhancements + +##### PW enable + +``` +password hardening enable +``` + +##### PW Class + PW class is the type of characters the user is required to enter when setting/updating a PW. + + There are 4 classes. (see description in arc section) + + The user will be able to choose whether to enforce all PW class characters in the PW or only a subset of the characters. + + A CLI command will be available to the user for this configuration. Once a user has selected the class types he wants to enforce (from a pre-defined options list), this will enforce the PW selected by the user to have at least 1 character from each class in the selected option. + + The CLI classes options will be as follows: + + None - Meaning no required classes. + + lower- lowerLowercase Characters + + lower-upper - Lowercase + Uppercase + + lower-upper-digit - Lowercase + Uppercase + Numbers + + lower-upper-digit-special - Lowercase + Uppercase + Numbers + Special + + multiple char enforcement + + There will be no enforcement of multiple characters from a specific class or a specific characters (be either letter or symbol) to appear in the PW. + +The CLI command to configure the PW class type will be along the following lines: + +``` +password complexity-class +``` + +##### PW Length + +``` +password length min +``` +Note: Where length is a number between 0 and 32. + +Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change + +##### PW Age + +* PW age expire + + + ``` + password age expiration + ``` + Notes: Where age is in days and between 1 and 365 days (default 180). + + +* PW Age Change Warning + + + ``` + password age warning + ``` + Notes: The warning_days can be configured between 1 and 30 days (default 15). + + +##### PW username-match + + password username-password-match + +##### PW Saving + + password history + +##### CLI permissions + The CLI commands should be allowed only to the admin user. Other users should be able to view the parameters but not change them. + +#### 1.9.2. Config DB Enhancements + This DB will include a new table "PASSW_CONF_TABLE" (Secure Password Table) +#### 1.9.3. Secure Password Table Schema +The table named PASSW_CONF_TABLE in CONF_DB will hold the follow key-values: + +``` +secure_enable=True/False +passwd_class=lower/lower-upper/lower-upper-digit/lower-upper-digit-special +passwd_expiration=N +passwd_expiration_warining=N +passwd_history=N +len_max=N +len_min=N +debug=True/False +retry=N +difok=N +minlen=N +dcredit=N +ucredit=N +lcredit=N +ocredit=N +minclass=N +maxrepeat=N +maxsequence=N +maxclassrepeat=N +dictpath= +``` + +Notes: + + Similar option will be saved in PASSW_CONF_TABLE in APPL_CONF.\ + the main difference is that other applications read from APPL_DB, and not from CONF_DB according Sonic arq. In addition, CONF_DB contain values requested by user, when APPL_DB contain the result values, meaning that if some option fail to set in the linux module the APPL_CONF will have the founded state of the option. + +### 1.10. 3rd Party Components +In this section you can find most of the options of pam-cracklib, chage and pwhistory, we are going to use just the options mention in the Arc chapter, the other option maybe could be use for future features + +#### 1.10.1. pam-cracklib + +Options: + +##### debug + This option makes the module write information to syslog(3) indicating the behavior of the module (this option does not write password information to the log file). +##### authtok_type=XXX + The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: ". The example word UNIX can be replaced with this option, by default it is empty. +##### retry=N + Prompt user at most N times before returning with error. The default is 1. + difok=N + This argument will change the default of 5 for the number of character changes in the new password that differentiate it from the old password. +##### minlen=N + The minimum acceptable size for the new password (plus one if credits are not disabled which is the default). In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (other, upper, lower and digit). The default for this parameter is 9 which is good for a old style UNIX password all of the same type of character but may be too low to exploit the added security of a md5 system. Note that there is a pair of length limits in Cracklib itself, a "way too short" limit of 4 which is hard coded in and a defined limit (6) that will be checked without reference to minlen. If you want to allow passwords as short as 5 characters you should not use this module. +##### dcredit=N + (N >= 0) This is the maximum credit for having digits in the new password. If you have less than or N digits, each digit will count +1 towards meeting the current minlen value. The default for dcredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of digits that must be met for a new password. + +##### ucredit=N + (N >= 0) This is the maximum credit for having upper case letters in the new password. If you have less than or N upper case letters each letter will count +1 towards meeting the current minlen value. The default for ucredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of upper case letters that must be met for a new password. + +##### lcredit=N + (N >= 0) This is the maximum credit for having lower case letters in the new password. If you have less than or N lower case letters, each letter will count +1 towards meeting the current minlen value. The default for lcredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of lower case letters that must be met for a new password. + +##### ocredit=N + (N >= 0) This is the maximum credit for having other characters in the new password. If you have less than or N other characters, each character will count +1 towards meeting the current minlen value. The default for ocredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of other characters that must be met for a new password. + +##### minclass=N + The minimum number of required classes of characters for the new password. The default number is zero. The four classes are digits, upper and lower letters and other characters. The difference to the credit check is that a specific class if of characters is not required. Instead N out of four of the classes are required. + maxrepeat=N + Reject passwords which contain more than N same consecutive characters. The default is 0 which means that this check is disabled. +##### maxsequence=N + Reject passwords which contain monotonic character sequences longer than N. The default is 0 which means that this check is disabled. Examples of such sequence are '12345' or 'fedcb'. Note that most such passwords will not pass the simplicity check unless the sequence is only a minor part of the password. +##### maxclassrepeat=N + Reject passwords which contain more than N consecutive characters of the same class. The default is 0 which means that this check is disabled. + reject_username + Check whether the name of the user in straight or reversed form is contained in the new password. If it is found the new password is rejected. +##### gecoscheck + Check whether the words from the GECOS field (usually full name of the user) longer than 3 characters in straight or reversed form are contained in the new password. If any such word is found the new password is rejected. +##### enforce_for_root + The module will return error on failed check also if the user changing the password is root. This option is off by default which means that just the message about the failed check is printed but root can change the password anyway. +##### use_authtok + This argument is used to force the module to not prompt the user for a new password but use the one provided by the previously stacked password module. +##### dictpath=/path/to/dict + Path to the cracklib dictionaries. + Module Types Provided + Only the password module type is provided. + +##### Return Values +###### PAM_SUCCESS + The new password passes all checks. +###### PAM_AUTHTOK_ERR + No new password was entered, the username could not be determined or the new password fails the strength checks. +###### PAM_AUTHTOK_RECOVERY_ERR + The old password was not supplied by a previous stacked module or got not requested from the user. The first error can happen if use_authtok is specified. +###### PAM_SERVICE_ERR + A internal error occurred. + +#### 1.10.2. PW Age + +![chage options](chage.JPG) + +The options which apply to the chage command are: + + -d, --lastday LAST_DAY + + Set the number of days since January 1st, 1970 when the password was last changed. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). + + -E, --expiredate EXPIRE_DATE + + Set the date or number of days since January 1, 1970 on which the users account will no longer be accessible. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). A user whose account is locked must contact the system administrator before being able to use the system again. + + Passing the number -1 as the EXPIRE_DATE will remove an account expiration date. + + -h, --help + + Display help message and exit. + + -i, --iso8601 + + When printing dates, use YYYY-MM-DD format. + + -I, --inactive INACTIVE + + Set the number of days of inactivity after a password has expired before the account is locked. The INACTIVE option is the number of days of inactivity. A user whose account is locked must contact the system administrator before being able to use the system again. + + Passing the number -1 as the INACTIVE will remove an accounts inactivity. + + -l, --list + + Show account aging information. + + -m, --mindays MIN_DAYS + + Set the minimum number of days between password changes to MIN_DAYS. A value of zero for this field indicates that the user may change their password at any time. + + -M, --maxdays MAX_DAYS + + Set the maximum number of days during which a password is valid. When MAX_DAYS plus LAST_DAY is less than the current day, the user will be required to change their password before being able to use their account. This occurrence can be planned for in advance by use of the -W option, which provides the user with advance warning. + + Passing the number -1 as MAX_DAYS will remove checking a passwords validity. + + -R, --root CHROOT_DIR + + Apply changes in the CHROOT_DIR directory and use the configuration files from the CHROOT_DIR directory. + + -W, --warndays WARN_DAYS + + Set the number of days of warning before a password change is required. The WARN_DAYS option is the number of days prior to the password expiring that a user will be warned their password is about to expire. + + If none of the options are selected, chage operates in an interactive fashion, prompting the user with the current values for all of the fields. Enter the new value to change the field, or leave the line blank to use the current value. The current value is displayed between a pair of [ ] marks. + +Notes: If we want to do "age" configuration globally and not per user, it necessary to modify this file: /etc/login.defs, example: + + PASS_MAX_DAYS 90 + PASS_WARN_AGE 7 + +#### 1.10.3. PW History +pam_pwhistory: PAM module to remember last passwords + +##### DESCRIPTION + + This module saves the last passwords for each user in order to force password change history and keep the user from alternating between the same password too frequently. + + This module does not work together with kerberos. In general, it does not make much sense to use this module in conjunction with NIS or LDAP, since the old passwords are stored on the local machine and are not available on another machine for password history checking. + +OPTIONS + +##### debug + + Turns on debugging via syslog(3). + use_authtok + + When password changing enforce the module to use the new password provided by a previously stacked password module (this is used in the example of the stacking of the pam_cracklib module documented below). +##### enforce_for_root + If this option is set, the check is enforced for root, too. +##### remember=N + + The last N passwords for each user are saved in /etc/security/opasswd. The default is 10. Value of 0 makes the module to keep the existing contents of the opasswd file unchanged. +##### retry=N + + Prompt user at most N times before returning with error. The default is 1. + authtok_type=STRING + + See pam_get_authtok(3) for more details. + MODULE TYPES PROVIDED + Only the password module type is provided. + +##### RETURN VALUES + PAM_AUTHTOK_ERR + + No new password was entered, the user aborted password change or new password couldn't be set. + PAM_IGNORE + + Password history was disabled. + PAM_MAXTRIES + + Password was rejected too often. + PAM_USER_UNKNOWN + + User is not known to system. +##### EXAMPLES + An example password section would be: + + #%PAM-1.0 + password required pam_pwhistory.so + password required pam_unix.so use_authtok + + In combination with pam_cracklib: + + #%PAM-1.0 + password required pam_cracklib.so retry=3 + password required pam_pwhistory.so use_authtok + password required pam_unix.so use_authtok + + +##### FILES + /etc/security/opasswd + + File with password history +### 1.11. Warmboot and Fastboot Design Impact + Not relevant. + +### 1.12. Restrictions/Limitations + the secure password feature is not supported on remote AAA. + LDAP/Radius/Tacacs is under customer responsability. + + +### 1.13. Test Plan + +#### 1.13.1. Setups + The test setup consists of a single switch (director and 1U, IB and Eth). + +#### 1.13.2. CLI configurational tests + +##### 2.2.1. Case 1: check basic configuration – good flow + +Test Objective: + + The test will create several secure password configurations, and verify them with show command and will verify in the Redis DB according the new table present in Config DB chapter. Also, it will verify the default values are configured correctly. + +#### 1.13.3. Precondition: + + Admin user is logged in and secure password feature is enabled with default values (can enable it in the test if needed). + +**Setup descriptions and objectives:** + +` `All Switches. + +|#|Test steps|Expected result| +| :-: | :-: | :-: | +||

If can’t be done in pre-test:

Reset secure password, so it will be enabled with default values.
Disable feature:

[no password security enable]

|secure password is disabled| +||

Enable feature:

[password security enable]

|secure password is enabled| +||

Perform show command

[show password security]

|Configured values are shown| +||

` `Verify that all the values are equal to the default:

Min password length: 8 (characters) 

Max password length: 64 (characters) 

Password age: 180 (days) 

Expiration warning message: 15 (days) 

Password history length: 5 

Character class: Lowercase, uppercase and digits 

Different username and password: Enabled 

|All values are equal to default| +||

Configure random min password

[password length minimal <0-32>]

|min password configured| +||

Configure random max password

[password length maximal <64-80>]

|max password configured| +||

Configure random age expiration password

[password age expiration<0-365>]

|age expiration password configured| +||

Configure random age warning password

[password age warning <0-30, **not larger than expiration**>]

|age warning password configured| +||

Configure random complexity-class password

[password complexity-class >lower| lower-upper | lower-upper-digit | lower-upper-digit-special<]

|complexity-class password configured| +||

Configure random password history

[password history <0-20>]

|History password configured| +||

Disable password and username to be different

[no password username-password-match enable]

(configuring to disabled because the default is enabled)

|username-password-match configured| +||

Perform a show command to verify all above configurations are set

[show password security]

|All configurations are set correctly| +||

Validate all appear in show running config

[show running-config]

|All appear| +||

Change the password to a password that e.g. length 33, different that old passwords, with lower case, upper case ,number and at least one char of:

`~!@#$%^&\*()-\_=+[{}];:',<.>

|Password is replaced| +||

Check “return to default, perform the “no” commands:

[no password age expiration]

[no password age warning]

[no password complexity-class]

[no password history]

|All configurations are configured and returned to default | +||

Perform a show command to verify all above configurations are set

[show password security]

|All configurations are set correctly– age to 180, warning to 15, complexity-class to lower-upper-digit, history to 5| +||

Disable the feature

[no password security enable]

|Configuration is set| +||[show running-config]|Feature is not set| + +##### 2.3.1. Case 2: check secure password history configuration + +Test Objective: + + The test will create several secure password history configurations. + +Precondition: + + Admin user is logged in and secure password feature is enabled. + +Setup descriptions and objectives: + +` `All Switches. + +|#|Test steps|Expected result| +| :-: | :-: | :-: | +||

Set history to <1-20>, CLI command: “password history <1-20>”

(possible: 0-20. Randomize 1-20. Let’s call it X. Also randomize a lower number for false try (1-Y).

|The history is configured to X| +||

Change password to a different password than current one and different to old ones (Repeat X-1 times, notice, in the middle there will be next step)

|Password is changed| +||

Inside the loop, somewhere in 1 - Y, try to set the initial password (that was already set).

|The password is not accepted.| +||

After X times, try to set the initial password (that was already set).

|The password is accepted.| +||

Disable the history

[password history 0]

|The configuration is set| +||Change to the same as last password|The password is set| + +#### 1.13.4. Case 3: check secure password age (expiration) and warning configuration + +Test Objective: + + The test will create several secure password age (expiration) and warning configurations. + +Precondition: + + Admin user is logged in and secure password feature is enabled. + +Setup descriptions and objectives: + + All Switches. + +|#|Test steps|Expected result| +| :-: | :-: | :-: | +||

Set age to X:

` `[password age expiration <1-365>]

|The age is configured to X| +||

Configure first without a warning

[password warning 0]

|The warning is configured to 0| +||

Log out

|The admin user is logged out| +||Log in|Logged in (if set to 1, only if not after 24:00, if after 24:00 it will be forced to change the password because it will be expired, and the test will fail…)| +||change the machine’s date to be larger than X (X+1 or more days from today)|Date is changed| +||Log out|Logged out| +||

Try to log in

|Password is forced to be changed| +||

Change the password to a legal one.

e.g. length 33, different that old passwords, with lower case, upper case, number.

|Password is changed and we are logged in| +||

Configure a warning to Y – notice, needs to be smaller than age.

[password warning <1-30>, not larger than expiration]

|configuration is set| +||change the machine’s date to be inside the range of the warning|Date is changed| +||

Log out

|The user is logged out| +||Log in|Logged in and the warning is shown| +||

Configure 0 to disable the age

[password age expiration 0]

|configuration is set| +||change the machine’s date to be larger than X (X+1 or more days from today)|Date is changed| +||Log out|Logged out.| +||Log in|Logged in, password is accepted.| + + + + +#### 1.13.5. Case 4 – sanity test +Test Objective: + + The test will create several secure password configurations and check users + +Precondition: + + Admin user is logged in and secure password feature is enabled. + +Setup descriptions and objectives: + + All Switches. + + +|#|Test steps|Expected result| +| :-: | :-: | :-: | +||` `Add a user with random capability (admin/monitor/v\_admin/unpriv) with a password that is accepted with the feature’s default values. e.g. length 33, different that old passwords, with lower case, upper case, number |User is added| +||Open a new session and try to login the user with the password that was set|Able to log in| +||

Configure random min password

[password length minimal <0-32>]

|min password configured| +||

Configure random max password

[password length maximal <64-80>]

|max password configured| +||

Configure random age expiration password

[password age expiration<0-365>]

|age expiration password configured| +||

Configure random age warning password

[password age warning <0-30>, not larger than expiration]

|Age warning password configured| +||

Configure random complexity-class password

[password complexity-class >lower| lower-upper | lower-upper-digit | lower-upper-digit-special<]

|complexity-class password configured| +||

Configure random password history

[password history <0-20>]

|History password configured| +||

Enable/Disable password and username to be different

[no] password username-password-match enable]

|username-password-match configured| +||

Perform a show command to verify all above configurations are set

[show password security]

|All configurations are set correctly| +||

Change password according to the new restrictions.

` `e.g. length 33, different that old passwords, with lower case, upper case, number and at least one char of:

`~!@#$%^&\*()-\_=+[{}];:',<.>

|password configured| +||Open a session and try to login to test user|Able to log in| +||Open another session to the same user and try to login with the most updated password|Logged in| +||Try to change password from second session to a non legal one|Password not configured| +||change password from second session to a legal one|Password configured| +||Logout from first session|Logged out| +||Log in from first session with new legal password|Logged in| + + + +#### 1.13.6. Negative cases +#### 1.13.7. Case 1: check basic configuration – bad flow with invalid input + +Test Objective: + + The test will try to set several secure password false configurations, and verify they ae not set. + +**Precondition:** + + Admin user is logged in and secure password feature is enabled. + +**Setup descriptions and objectives:** + + All Switches. + + +|#|Test steps|Expected result| +| :-: | :-: | :-: | +||

Perform a show command to verify the configuration later

[show password security]

|Configured values are shown| +||

Configure min password with random false value:

` `Negative numbers, letters, chars, fragments (e.g. 4.5), numbers **not** in the allowed range (0-32)

[password length minimal <>]

|min password not configured, error message is returned| +||

Configure max password with random false value:

` `Negative numbers, letters, chars, fragments (e.g. 4.5), numbers **not** in the allowed range(64-80)

[password length maximal <>]

|max password not configured, error message is returned| +||

Configure age expiration password with random false value:

` `Negative numbers, letters, chars, fragments (e.g. 4.5), numbers **not** in the allowed range(0-365)

[password age expiration<>]

|age expiration password not configured, error message is returned| +||

Configure age warning password with random false value:

` `Negative numbers, letters, chars, fragments (e.g. 4.5), numbers **not** in the allowed range(0-30)

[password age warning <>]

|age warning password not configured, error message is returned| +||

Configure complexity-class password with random false value:

` `Negative numbers, letters, chars, fragments (e.g. 4.5), it can be any data **not** equal to: “lower| lower-upper | lower-upper-digit | lower-upper-digit-special”.

[password complexity-class <>]

|complexity-class password not configured, error message is returned| +||

Configure history password with random false value:

Negative numbers, letters, chars, fragments (e.g. 4.5), numbers **not** in the allowed range (0-20)

[password history <>]

|history password not configured, error message is returned| +||

Configure username-password-match with random false value that is **not** enable

[password username-password-match <>]

|username-password-match not configured, error message is returned| +||

Try to configure

[password age expiration <1-14>]

` `lower than warning that is set to 15

|Should return a message – warning can’t larger than age.| +||

Perform a show command to verify all above configurations are not set

[show password security]

|All configurations are not changed| +||

Try to configure a very long password (above the max, even hundreds of chars)

[username admin password X]

|Should fail – longer than maximum| + + +#### 1.13.8. Test Open Issues + +Is this feature support when user uses multiple sessions in same time, i.e: + Try to set a new password from 2 different sessions at the same time (for the same user). – do we have a lock mechanism? What do we expect to happen? + + \ No newline at end of file diff --git a/doc/passw_hardening/passh_arc_sonic.drawio.png b/doc/passw_hardening/passh_arc_sonic.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..81efbfaddb8debc04ef8e0482a83ce5735ce5172 GIT binary patch literal 27848 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 Yjg3n6F6+QgligEQe4$YN+&c3A0Bl(`jsO4v literal 0 HcmV?d00001 diff --git a/doc/passw_hardening/ph_diagram.jpg b/doc/passw_hardening/ph_diagram.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e6ffa8eef1d4b36f019a70b542f157facf3e3fdd GIT binary patch literal 30903 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 literal 0 HcmV?d00001 From f2fed5f640172df773378e628fccd8badb8520f9 Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Sun, 3 Oct 2021 17:18:52 +0300 Subject: [PATCH 02/16] fix some cosmetics details & add notes --- doc/passw_hardening/hld_password_hardening.md | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index 8b2524b808f..e022829b0b8 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -138,11 +138,14 @@ Arc design diagram\ The minimum length of the PW should be subject to a user change. - The user will be able to change the password minimum length if he has the necessary permissions to change the PW. The CLI command to change the PW: + The user will be able to change the password minimum length if he has the necessary permissions to change the PW. + Implementation: + In order to implement it, the cracklib option minlen=N should be set. -Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change + Note: + Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change ##### PW Age Along with every PW set to a user, attached to it is the age of the PW - the amount of time that has passed since a PW change has occurred. @@ -165,23 +168,25 @@ Once the user changed the minimum password length - the settings will be applied To support it, can be use chage option "--warndays" -Notes: -For implement the "aging" we need to change the /etc/login.def file and set max days and warning days, this changes affection globally, meaning all new users. -For read the information per user we will use the "chage" library. -In addition, when we change the file /etc/login.def its change globally by only new users, so basically for change existing users expired day we need to iterate every one of them using the "chage" lib. +Aging(expire) implementation : + For implement the "aging" we need to change the /etc/login.def file and set max days and warning days, this changes affection globally, meaning all new users. + For read the information per user we will use the "chage" library. + In addition, when we change the file /etc/login.def its change globally by only new users, so basically for change existing users expired day we need to iterate every one of them using the "chage" lib. ##### PW username-match -By enabling this feature, the user will not be permitted to set the same username & password + By enabling this feature, the user will not be permitted to set the same username & password ##### PW Saving -Saved previous passwords in the DB, for enable this. is necessary to set how many old password you would like to save. + Saved previous passwords in the DB, for enable this. is necessary to set how many old password you would like to save. -Note: will be support by using pam_pwhistory.so, remmember=N option. -For saving password with sha512, need to modify the /etc/pam.d/system-auth-a file to contain this line: + Implementation: will be support by using pam_pwhistory.so, remmember=N option. + + Note: + For saving password with sha512, need to modify the /etc/pam.d/system-auth-a file to contain this line: - password sufficient pam_unix.so sha512 shadow use_authtok + password sufficient pam_unix.so sha512 shadow use_authtok ### 1.8. SAI API no changed. @@ -642,7 +647,7 @@ Test Objective: Admin user is logged in and secure password feature is enabled. -**Setup descriptions and objectives:** +Setup descriptions and objectives: All Switches. @@ -661,7 +666,8 @@ Test Objective: ||

Perform a show command to verify all above configurations are not set

[show password security]

|All configurations are not changed| ||

Try to configure a very long password (above the max, even hundreds of chars)

[username admin password X]

|Should fail – longer than maximum| - +Note: + There are 2 DB to test: CONF_DB and APPL_DB, need to be test both of them in every test case. #### 1.13.8. Test Open Issues Is this feature support when user uses multiple sessions in same time, i.e: From d0cbc7a8d9dc887a5c9e63e2bafdebfb8ad9716a Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Sun, 10 Oct 2021 12:29:58 +0300 Subject: [PATCH 03/16] add init chapter & few remarks --- doc/passw_hardening/hld_password_hardening.md | 455 ++++++++++-------- doc/passw_hardening/ph_diagram.jpg | Bin 30903 -> 29750 bytes 2 files changed, 248 insertions(+), 207 deletions(-) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index e022829b0b8..bc543d175ed 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -1,6 +1,8 @@ # PW Hardening Design # ## 1. Table of Content + + * 1. [Table of Content](#TableofContent) * 1.1. [Revision](#Revision) * 1.2. [Scope](#Scope) @@ -11,15 +13,16 @@ * 1.7. [High-Level Design](#High-LevelDesign) * 1.7.1. [Flow description:](#Flowdescription:) * 1.7.2. [Password Hardening Constrains](#PasswordHardeningConstrains) - * 1.8. [SAI API](#SAIAPI) - * 1.9. [Configuration and management](#Configurationandmanagement) - * 1.9.1. [CLI/YANG model Enhancements](#CLIYANGmodelEnhancements) - * 1.9.2. [Config DB Enhancements](#ConfigDBEnhancements) - * 1.9.3. [Secure Password Table Schema](#SecurePasswordTableSchema) - * 1.10. [3rd Party Components](#rdPartyComponents) - * 1.10.1. [pam-cracklib](#pam-cracklib) - * 1.10.2. [PW Age](#PWAge) - * 1.10.3. [PW History](#PWHistory) + * 1.8. [Init Flow](#InitFlow) + * 1.8.1. [Compilation](#Compilation) + * 1.8.2. [dependencies](#dependencies) + * 1.8.3. [Feature default](#Featuredefault) + * 1.8.4. [How daemon work internally:](#Howdaemonworkinternally:) + * 1.9. [SAI API](#SAIAPI) + * 1.10. [Configuration and management](#Configurationandmanagement) + * 1.10.1. [CLI/YANG model Enhancements](#CLIYANGmodelEnhancements) + * 1.10.2. [Config DB Enhancements](#ConfigDBEnhancements) + * 1.10.3. [Secure Password Table Schema](#SecurePasswordTableSchema) * 1.11. [Warmboot and Fastboot Design Impact](#WarmbootandFastbootDesignImpact) * 1.12. [Restrictions/Limitations](#RestrictionsLimitations) * 1.13. [Test Plan](#TestPlan) @@ -31,6 +34,17 @@ * 1.13.6. [Negative cases](#Negativecases) * 1.13.7. [Case 1: check basic configuration – bad flow with invalid input](#Case1:checkbasicconfigurationbadflowwithinvalidinput) * 1.13.8. [Test Open Issues](#TestOpenIssues) + * 1.14. [3rd Party Components](#rdPartyComponents) + * 1.14.1. [pam-cracklib](#pam-cracklib) + * 1.14.2. [PW Age](#PWAge) + * 1.14.3. [PW History](#PWHistory) + + + + ### 1.1. Revision @@ -68,7 +82,7 @@ Arc design diagram\ User password as explained before is the first line defence, in order to support it according the requirement section and user preferences, the secure password feature need a strengh-checking for password. - The feature will use 3 linux libs: pam-cracklib, chage and pam_pwhistory.so + The feature will use 2 linux libs: pam-cracklib, chage and pam_pwhistory.so pam-cracklib: This module can be plugged into the password stack of a given application to provide some plug-in strength-checking for passwords. @@ -77,7 +91,7 @@ Arc design diagram\ chage: support the requirement of PW Aging, change user password expiry information - pam_pwhistory - PAM module to remember last passwords + pam_pwhistory - PAM module to remember last passwords (seen that Debian already supported it without installing this package) Note: See linux 3d party component chapter for more description @@ -128,6 +142,7 @@ Arc design diagram\ To request at least one character of every class, the PASSWD daemon will set: pam-cracklib options: lcredit=-1, ucredit=-1, dcredit=-1. (meaning that the user need at least one character of the types.) + See explanation of cracklib options in 3rd Party component chapter. ##### PW Length PW length is a base requirement for the PW. @@ -181,19 +196,42 @@ Aging(expire) implementation : ##### PW Saving Saved previous passwords in the DB, for enable this. is necessary to set how many old password you would like to save. - Implementation: will be support by using pam_pwhistory.so, remmember=N option. + Implementation: will be support by using pam_pwhistory.so, remember=N option. + Seen that in Debian its not necessary to install this package. Its enough to add the remember=N option to the common-password file. Note: For saving password with sha512, need to modify the /etc/pam.d/system-auth-a file to contain this line: password sufficient pam_unix.so sha512 shadow use_authtok -### 1.8. SAI API +### 1.8. Init Flow +#### 1.8.1. Compilation + This feature will be disable by default in compilation stage, its meaning that it will be not compile, just in case the user will change the makefile setting to enable, this feature will be compile. + + In addition, the feature will have CLI as "plugin", meaning that when the feature is not compile even the feature CLI will be not appear in the CLI of the switch, and vice versa, when the feature will be compile the feature CLI plugin will be added to the general switch CLI. + +#### 1.8.2. dependencies + service dependencies: SWSS & DB containers. + Description: + Password Hardening Daemon, the service that trigger this daemon, should start after SWSS & DB containers start. + +#### 1.8.3. Feature default + Even when user will decide to add the feature in compilation the feature will be disable by default. + + The feature in general can be enable when changing the CONF_DB of the feature table to passw_hardening_enable=True/False. + +#### 1.8.4. How daemon work internally: + In case the user decided to compile the feature. The password hardening daemon will be started and running always, but it will do nothing, meaning the process will be in sleep mode, until the passw_hardening_enable field in the Redis DB will be changed to enable, then the service will be awake, and will be possible to use. + + Note: + This approach can support reset of the system, because the daemon automatly can verify if he should be awake or not. + +### 1.9. SAI API no changed. -### 1.9. Configuration and management +### 1.10. Configuration and management -#### 1.9.1. CLI/YANG model Enhancements +#### 1.10.1. CLI/YANG model Enhancements ##### PW enable @@ -272,13 +310,13 @@ Once the user changed the minimum password length - the settings will be applied ##### CLI permissions The CLI commands should be allowed only to the admin user. Other users should be able to view the parameters but not change them. -#### 1.9.2. Config DB Enhancements +#### 1.10.2. Config DB Enhancements This DB will include a new table "PASSW_CONF_TABLE" (Secure Password Table) -#### 1.9.3. Secure Password Table Schema +#### 1.10.3. Secure Password Table Schema The table named PASSW_CONF_TABLE in CONF_DB will hold the follow key-values: ``` -secure_enable=True/False +passw_hardening_enable=True/False # enable/disable the feature passwd_class=lower/lower-upper/lower-upper-digit/lower-upper-digit-special passwd_expiration=N passwd_expiration_warining=N @@ -289,7 +327,7 @@ debug=True/False retry=N difok=N minlen=N -dcredit=N +dcredit=N ucredit=N lcredit=N ocredit=N @@ -301,196 +339,13 @@ dictpath= ``` Notes: - - Similar option will be saved in PASSW_CONF_TABLE in APPL_CONF.\ +* More descriptions of the field can be found in 3rd Party Chaper +* Similar option will be saved in PASSW_CONF_TABLE in APPL_CONF.\ the main difference is that other applications read from APPL_DB, and not from CONF_DB according Sonic arq. In addition, CONF_DB contain values requested by user, when APPL_DB contain the result values, meaning that if some option fail to set in the linux module the APPL_CONF will have the founded state of the option. -### 1.10. 3rd Party Components -In this section you can find most of the options of pam-cracklib, chage and pwhistory, we are going to use just the options mention in the Arc chapter, the other option maybe could be use for future features - -#### 1.10.1. pam-cracklib - -Options: - -##### debug - This option makes the module write information to syslog(3) indicating the behavior of the module (this option does not write password information to the log file). -##### authtok_type=XXX - The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: ". The example word UNIX can be replaced with this option, by default it is empty. -##### retry=N - Prompt user at most N times before returning with error. The default is 1. - difok=N - This argument will change the default of 5 for the number of character changes in the new password that differentiate it from the old password. -##### minlen=N - The minimum acceptable size for the new password (plus one if credits are not disabled which is the default). In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (other, upper, lower and digit). The default for this parameter is 9 which is good for a old style UNIX password all of the same type of character but may be too low to exploit the added security of a md5 system. Note that there is a pair of length limits in Cracklib itself, a "way too short" limit of 4 which is hard coded in and a defined limit (6) that will be checked without reference to minlen. If you want to allow passwords as short as 5 characters you should not use this module. -##### dcredit=N - (N >= 0) This is the maximum credit for having digits in the new password. If you have less than or N digits, each digit will count +1 towards meeting the current minlen value. The default for dcredit is 1 which is the recommended value for minlen less than 10. - (N < 0) This is the minimum number of digits that must be met for a new password. - -##### ucredit=N - (N >= 0) This is the maximum credit for having upper case letters in the new password. If you have less than or N upper case letters each letter will count +1 towards meeting the current minlen value. The default for ucredit is 1 which is the recommended value for minlen less than 10. - (N < 0) This is the minimum number of upper case letters that must be met for a new password. - -##### lcredit=N - (N >= 0) This is the maximum credit for having lower case letters in the new password. If you have less than or N lower case letters, each letter will count +1 towards meeting the current minlen value. The default for lcredit is 1 which is the recommended value for minlen less than 10. - (N < 0) This is the minimum number of lower case letters that must be met for a new password. - -##### ocredit=N - (N >= 0) This is the maximum credit for having other characters in the new password. If you have less than or N other characters, each character will count +1 towards meeting the current minlen value. The default for ocredit is 1 which is the recommended value for minlen less than 10. - (N < 0) This is the minimum number of other characters that must be met for a new password. - -##### minclass=N - The minimum number of required classes of characters for the new password. The default number is zero. The four classes are digits, upper and lower letters and other characters. The difference to the credit check is that a specific class if of characters is not required. Instead N out of four of the classes are required. - maxrepeat=N - Reject passwords which contain more than N same consecutive characters. The default is 0 which means that this check is disabled. -##### maxsequence=N - Reject passwords which contain monotonic character sequences longer than N. The default is 0 which means that this check is disabled. Examples of such sequence are '12345' or 'fedcb'. Note that most such passwords will not pass the simplicity check unless the sequence is only a minor part of the password. -##### maxclassrepeat=N - Reject passwords which contain more than N consecutive characters of the same class. The default is 0 which means that this check is disabled. - reject_username - Check whether the name of the user in straight or reversed form is contained in the new password. If it is found the new password is rejected. -##### gecoscheck - Check whether the words from the GECOS field (usually full name of the user) longer than 3 characters in straight or reversed form are contained in the new password. If any such word is found the new password is rejected. -##### enforce_for_root - The module will return error on failed check also if the user changing the password is root. This option is off by default which means that just the message about the failed check is printed but root can change the password anyway. -##### use_authtok - This argument is used to force the module to not prompt the user for a new password but use the one provided by the previously stacked password module. -##### dictpath=/path/to/dict - Path to the cracklib dictionaries. - Module Types Provided - Only the password module type is provided. - -##### Return Values -###### PAM_SUCCESS - The new password passes all checks. -###### PAM_AUTHTOK_ERR - No new password was entered, the username could not be determined or the new password fails the strength checks. -###### PAM_AUTHTOK_RECOVERY_ERR - The old password was not supplied by a previous stacked module or got not requested from the user. The first error can happen if use_authtok is specified. -###### PAM_SERVICE_ERR - A internal error occurred. - -#### 1.10.2. PW Age - -![chage options](chage.JPG) - -The options which apply to the chage command are: - - -d, --lastday LAST_DAY - - Set the number of days since January 1st, 1970 when the password was last changed. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). - - -E, --expiredate EXPIRE_DATE - - Set the date or number of days since January 1, 1970 on which the users account will no longer be accessible. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). A user whose account is locked must contact the system administrator before being able to use the system again. - - Passing the number -1 as the EXPIRE_DATE will remove an account expiration date. - - -h, --help - - Display help message and exit. - - -i, --iso8601 - - When printing dates, use YYYY-MM-DD format. - - -I, --inactive INACTIVE - - Set the number of days of inactivity after a password has expired before the account is locked. The INACTIVE option is the number of days of inactivity. A user whose account is locked must contact the system administrator before being able to use the system again. - - Passing the number -1 as the INACTIVE will remove an accounts inactivity. - - -l, --list - - Show account aging information. - - -m, --mindays MIN_DAYS - - Set the minimum number of days between password changes to MIN_DAYS. A value of zero for this field indicates that the user may change their password at any time. - - -M, --maxdays MAX_DAYS - - Set the maximum number of days during which a password is valid. When MAX_DAYS plus LAST_DAY is less than the current day, the user will be required to change their password before being able to use their account. This occurrence can be planned for in advance by use of the -W option, which provides the user with advance warning. - - Passing the number -1 as MAX_DAYS will remove checking a passwords validity. - - -R, --root CHROOT_DIR - - Apply changes in the CHROOT_DIR directory and use the configuration files from the CHROOT_DIR directory. - - -W, --warndays WARN_DAYS - - Set the number of days of warning before a password change is required. The WARN_DAYS option is the number of days prior to the password expiring that a user will be warned their password is about to expire. - - If none of the options are selected, chage operates in an interactive fashion, prompting the user with the current values for all of the fields. Enter the new value to change the field, or leave the line blank to use the current value. The current value is displayed between a pair of [ ] marks. - -Notes: If we want to do "age" configuration globally and not per user, it necessary to modify this file: /etc/login.defs, example: - - PASS_MAX_DAYS 90 - PASS_WARN_AGE 7 - -#### 1.10.3. PW History -pam_pwhistory: PAM module to remember last passwords - -##### DESCRIPTION - - This module saves the last passwords for each user in order to force password change history and keep the user from alternating between the same password too frequently. - - This module does not work together with kerberos. In general, it does not make much sense to use this module in conjunction with NIS or LDAP, since the old passwords are stored on the local machine and are not available on another machine for password history checking. - -OPTIONS - -##### debug - - Turns on debugging via syslog(3). - use_authtok - - When password changing enforce the module to use the new password provided by a previously stacked password module (this is used in the example of the stacking of the pam_cracklib module documented below). -##### enforce_for_root - If this option is set, the check is enforced for root, too. -##### remember=N - - The last N passwords for each user are saved in /etc/security/opasswd. The default is 10. Value of 0 makes the module to keep the existing contents of the opasswd file unchanged. -##### retry=N - - Prompt user at most N times before returning with error. The default is 1. - authtok_type=STRING - - See pam_get_authtok(3) for more details. - MODULE TYPES PROVIDED - Only the password module type is provided. - -##### RETURN VALUES - PAM_AUTHTOK_ERR - - No new password was entered, the user aborted password change or new password couldn't be set. - PAM_IGNORE - - Password history was disabled. - PAM_MAXTRIES - - Password was rejected too often. - PAM_USER_UNKNOWN - - User is not known to system. -##### EXAMPLES - An example password section would be: - - #%PAM-1.0 - password required pam_pwhistory.so - password required pam_unix.so use_authtok - - In combination with pam_cracklib: - - #%PAM-1.0 - password required pam_cracklib.so retry=3 - password required pam_pwhistory.so use_authtok - password required pam_unix.so use_authtok - - -##### FILES - /etc/security/opasswd +* values like password_expiration, need to be wrote in the DB under username, ie: username1/passwd_expiration + because different users can have different remain of expiration time. - File with password history ### 1.11. Warmboot and Fastboot Design Impact Not relevant. @@ -673,4 +528,190 @@ Note: Is this feature support when user uses multiple sessions in same time, i.e: Try to set a new password from 2 different sessions at the same time (for the same user). – do we have a lock mechanism? What do we expect to happen? - \ No newline at end of file + +### 1.14. 3rd Party Components +In this section you can find most of the options of pam-cracklib, chage and pwhistory, we are going to use just the options mention in the Arc chapter, the other option maybe could be use for future features + +#### 1.14.1. pam-cracklib + +Options: + +##### debug + This option makes the module write information to syslog(3) indicating the behavior of the module (this option does not write password information to the log file). +##### authtok_type=XXX + The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: ". The example word UNIX can be replaced with this option, by default it is empty. +##### retry=N + Prompt user at most N times before returning with error. The default is 1. +##### difok=N + This argument will change the default of 5 for the number of character changes in the new password that differentiate it from the old password. +##### minlen=N + The minimum acceptable size for the new password (plus one if credits are not disabled which is the default). In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (other, upper, lower and digit). The default for this parameter is 9 which is good for a old style UNIX password all of the same type of character but may be too low to exploit the added security of a md5 system. Note that there is a pair of length limits in Cracklib itself, a "way too short" limit of 4 which is hard coded in and a defined limit (6) that will be checked without reference to minlen. If you want to allow passwords as short as 5 characters you should not use this module. +##### dcredit=N + (N >= 0) This is the maximum credit for having digits in the new password. If you have less than or N digits, each digit will count +1 towards meeting the current minlen value. The default for dcredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of digits that must be met for a new password. + +##### ucredit=N + (N >= 0) This is the maximum credit for having upper case letters in the new password. If you have less than or N upper case letters each letter will count +1 towards meeting the current minlen value. The default for ucredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of upper case letters that must be met for a new password. + +##### lcredit=N + (N >= 0) This is the maximum credit for having lower case letters in the new password. If you have less than or N lower case letters, each letter will count +1 towards meeting the current minlen value. The default for lcredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of lower case letters that must be met for a new password. + +##### ocredit=N + (N >= 0) This is the maximum credit for having other characters in the new password. If you have less than or N other characters, each character will count +1 towards meeting the current minlen value. The default for ocredit is 1 which is the recommended value for minlen less than 10. + (N < 0) This is the minimum number of other characters that must be met for a new password. + +##### minclass=N + The minimum number of required classes of characters for the new password. The default number is zero. The four classes are digits, upper and lower letters and other characters. The difference to the credit check is that a specific class if of characters is not required. Instead N out of four of the classes are required. + maxrepeat=N + Reject passwords which contain more than N same consecutive characters. The default is 0 which means that this check is disabled. +##### maxsequence=N + Reject passwords which contain monotonic character sequences longer than N. The default is 0 which means that this check is disabled. Examples of such sequence are '12345' or 'fedcb'. Note that most such passwords will not pass the simplicity check unless the sequence is only a minor part of the password. +##### maxclassrepeat=N + Reject passwords which contain more than N consecutive characters of the same class. The default is 0 which means that this check is disabled. + reject_username + Check whether the name of the user in straight or reversed form is contained in the new password. If it is found the new password is rejected. +##### gecoscheck + Check whether the words from the GECOS field (usually full name of the user) longer than 3 characters in straight or reversed form are contained in the new password. If any such word is found the new password is rejected. +##### enforce_for_root + The module will return error on failed check also if the user changing the password is root. This option is off by default which means that just the message about the failed check is printed but root can change the password anyway. +##### use_authtok + This argument is used to force the module to not prompt the user for a new password but use the one provided by the previously stacked password module. +##### dictpath=/path/to/dict + Path to the cracklib dictionaries. + Module Types Provided + Only the password module type is provided. + +##### Return Values +###### PAM_SUCCESS + The new password passes all checks. +###### PAM_AUTHTOK_ERR + No new password was entered, the username could not be determined or the new password fails the strength checks. +###### PAM_AUTHTOK_RECOVERY_ERR + The old password was not supplied by a previous stacked module or got not requested from the user. The first error can happen if use_authtok is specified. +###### PAM_SERVICE_ERR + A internal error occurred. + +#### 1.14.2. PW Age + +![chage options](chage.JPG) + +The options which apply to the chage command are: + + -d, --lastday LAST_DAY + + Set the number of days since January 1st, 1970 when the password was last changed. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). + + -E, --expiredate EXPIRE_DATE + + Set the date or number of days since January 1, 1970 on which the users account will no longer be accessible. The date may also be expressed in the format YYYY-MM-DD (or the format more commonly used in your area). A user whose account is locked must contact the system administrator before being able to use the system again. + + Passing the number -1 as the EXPIRE_DATE will remove an account expiration date. + + -h, --help + + Display help message and exit. + + -i, --iso8601 + + When printing dates, use YYYY-MM-DD format. + + -I, --inactive INACTIVE + + Set the number of days of inactivity after a password has expired before the account is locked. The INACTIVE option is the number of days of inactivity. A user whose account is locked must contact the system administrator before being able to use the system again. + + Passing the number -1 as the INACTIVE will remove an accounts inactivity. + + -l, --list + + Show account aging information. + + -m, --mindays MIN_DAYS + + Set the minimum number of days between password changes to MIN_DAYS. A value of zero for this field indicates that the user may change their password at any time. + + -M, --maxdays MAX_DAYS + + Set the maximum number of days during which a password is valid. When MAX_DAYS plus LAST_DAY is less than the current day, the user will be required to change their password before being able to use their account. This occurrence can be planned for in advance by use of the -W option, which provides the user with advance warning. + + Passing the number -1 as MAX_DAYS will remove checking a passwords validity. + + -R, --root CHROOT_DIR + + Apply changes in the CHROOT_DIR directory and use the configuration files from the CHROOT_DIR directory. + + -W, --warndays WARN_DAYS + + Set the number of days of warning before a password change is required. The WARN_DAYS option is the number of days prior to the password expiring that a user will be warned their password is about to expire. + + If none of the options are selected, chage operates in an interactive fashion, prompting the user with the current values for all of the fields. Enter the new value to change the field, or leave the line blank to use the current value. The current value is displayed between a pair of [ ] marks. + +Notes: If we want to do "age" configuration globally and not per user, it necessary to modify this file: /etc/login.defs, example: + + PASS_MAX_DAYS 90 + PASS_WARN_AGE 7 + +#### 1.14.3. PW History +pam_pwhistory: PAM module to remember last passwords + +##### DESCRIPTION + + This module saves the last passwords for each user in order to force password change history and keep the user from alternating between the same password too frequently. + + This module does not work together with kerberos. In general, it does not make much sense to use this module in conjunction with NIS or LDAP, since the old passwords are stored on the local machine and are not available on another machine for password history checking. + +OPTIONS + +##### debug + + Turns on debugging via syslog(3). + use_authtok + + When password changing enforce the module to use the new password provided by a previously stacked password module (this is used in the example of the stacking of the pam_cracklib module documented below). +##### enforce_for_root + If this option is set, the check is enforced for root, too. +##### remember=N + + The last N passwords for each user are saved in /etc/security/opasswd. The default is 10. Value of 0 makes the module to keep the existing contents of the opasswd file unchanged. +##### retry=N + + Prompt user at most N times before returning with error. The default is 1. + authtok_type=STRING + + See pam_get_authtok(3) for more details. + MODULE TYPES PROVIDED + Only the password module type is provided. + +##### RETURN VALUES + PAM_AUTHTOK_ERR + + No new password was entered, the user aborted password change or new password couldn't be set. + PAM_IGNORE + + Password history was disabled. + PAM_MAXTRIES + + Password was rejected too often. + PAM_USER_UNKNOWN + + User is not known to system. +##### EXAMPLES + An example password section would be: + + #%PAM-1.0 + password required pam_pwhistory.so + password required pam_unix.so use_authtok + + In combination with pam_cracklib: + + #%PAM-1.0 + password required pam_cracklib.so retry=3 + password required pam_pwhistory.so use_authtok + password required pam_unix.so use_authtok + + +##### FILES + /etc/security/opasswd + + File with password history \ No newline at end of file diff --git a/doc/passw_hardening/ph_diagram.jpg b/doc/passw_hardening/ph_diagram.jpg index e6ffa8eef1d4b36f019a70b542f157facf3e3fdd..56555e732caf34b09ba6f5c28284ff3f9d351784 100644 GIT binary patch literal 29750 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 From 242a436e0c9730ba7d638f1a6dde05a1e9a25418 Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Sun, 10 Oct 2021 16:30:32 +0300 Subject: [PATCH 04/16] semantics & modify CLI commands according Sonic CLI convention --- doc/passw_hardening/hld_password_hardening.md | 76 ++++++++++++++----- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index bc543d175ed..2abb33940c9 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -206,25 +206,25 @@ Aging(expire) implementation : ### 1.8. Init Flow #### 1.8.1. Compilation - This feature will be disable by default in compilation stage, its meaning that it will be not compile, just in case the user will change the makefile setting to enable, this feature will be compile. + This feature will be disabled by default in the compilation stage, its meaning that it will be not compiled, only when the user will change the makefile setting to enable, this feature will be compiled. - In addition, the feature will have CLI as "plugin", meaning that when the feature is not compile even the feature CLI will be not appear in the CLI of the switch, and vice versa, when the feature will be compile the feature CLI plugin will be added to the general switch CLI. + In addition, the feature will have CLI as a "plugin", meaning that when the feature is not compiled will be not appear in the CLI of the switch, and vice versa. #### 1.8.2. dependencies service dependencies: SWSS & DB containers. Description: - Password Hardening Daemon, the service that trigger this daemon, should start after SWSS & DB containers start. + Password Hardening Daemon, the service that triggers this daemon, should start after SWSS & DB containers start. #### 1.8.3. Feature default - Even when user will decide to add the feature in compilation the feature will be disable by default. + When a user decides to add the feature in the compilation the feature will be disabled by default. - The feature in general can be enable when changing the CONF_DB of the feature table to passw_hardening_enable=True/False. + The feature in general can be enabled when changing the CONF_DB of the feature table to passw_hardening_enable=True/False. -#### 1.8.4. How daemon work internally: - In case the user decided to compile the feature. The password hardening daemon will be started and running always, but it will do nothing, meaning the process will be in sleep mode, until the passw_hardening_enable field in the Redis DB will be changed to enable, then the service will be awake, and will be possible to use. +#### 1.8.4. How the daemon works internally: + In case the user decides to compile the feature. The password hardening daemon will be started and running always, but it will do nothing. Meaning the process will be in sleep mode, until the passw_hardening_enable field in the Redis DB will be changed to enable, then the service will activate, and will be functional. Note: - This approach can support reset of the system, because the daemon automatly can verify if he should be awake or not. + This approach can support reset of the system, because the daemon can automatically can verify if he should be awake or not. ### 1.9. SAI API no changed. @@ -234,9 +234,14 @@ Aging(expire) implementation : #### 1.10.1. CLI/YANG model Enhancements ##### PW enable +Set configuration: +``` +config passwh enable +``` +Get configuration: ``` -password hardening enable +show passwh ``` ##### PW Class @@ -266,15 +271,26 @@ password hardening enable The CLI command to configure the PW class type will be along the following lines: +Set configuration: ``` -password complexity-class +config passwh complexity-class +``` +Get configuration: +``` +show passwh complexity-class ``` - ##### PW Length +Set configuration: +``` +config passwh length min ``` -password length min + +Get configuration: ``` +show passwh length min +``` + Note: Where length is a number between 0 and 32. Once the user changed the minimum password length - the settings will be applied to the config node and will be enforced on the next pw change @@ -283,29 +299,51 @@ Once the user changed the minimum password length - the settings will be applied * PW age expire - + Set configuration: + ``` + config passwh age expiration + ``` + + Get configuration: ``` - password age expiration + show passwh age expiration ``` + Notes: Where age is in days and between 1 and 365 days (default 180). - - * PW Age Change Warning + Set configuration: + ``` + config passwh age warning + ``` + Get configuration: ``` - password age warning + show passwh age warning ``` + Notes: The warning_days can be configured between 1 and 30 days (default 15). ##### PW username-match - password username-password-match +Set configuration: + + config passwh username-password-match + +Get configuration: + + show passwh username-password-match + ##### PW Saving +Set configuration: + + config passwh history + +Get configuration: - password history + show passwh history ##### CLI permissions The CLI commands should be allowed only to the admin user. Other users should be able to view the parameters but not change them. From 4b834f0e0cad83c26a4e4ccbf11e411300f7abed Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Sun, 10 Oct 2021 17:00:03 +0300 Subject: [PATCH 05/16] add field in DB per user --- doc/passw_hardening/hld_password_hardening.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index 2abb33940c9..d0882de803f 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -357,8 +357,11 @@ The table named PASSW_CONF_TABLE in CONF_DB will hold the follow key-values: passw_hardening_enable=True/False # enable/disable the feature passwd_class=lower/lower-upper/lower-upper-digit/lower-upper-digit-special passwd_expiration=N +passwd_expiration/user=N passwd_expiration_warining=N +passwd_expiration_warining/user=N passwd_history=N +passwd_history/user=N len_max=N len_min=N debug=True/False From 8c2e89a7baa80bbb70d59d39fdfbb2b27d609eea Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Thu, 21 Oct 2021 11:26:43 +0300 Subject: [PATCH 06/16] add yang module, ABNF description, init flow chapter --- doc/passw_hardening/hld_password_hardening.md | 815 +++++++++--------- doc/passw_hardening/sonic-passwh.yang | 82 ++ 2 files changed, 490 insertions(+), 407 deletions(-) create mode 100644 doc/passw_hardening/sonic-passwh.yang diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index d0882de803f..28871608f95 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -17,26 +17,21 @@ * 1.8.1. [Compilation](#Compilation) * 1.8.2. [dependencies](#dependencies) * 1.8.3. [Feature default](#Featuredefault) - * 1.8.4. [How daemon work internally:](#Howdaemonworkinternally:) + * 1.8.4. [How the daemon works internally:](#Howthedaemonworksinternally:) * 1.9. [SAI API](#SAIAPI) * 1.10. [Configuration and management](#Configurationandmanagement) - * 1.10.1. [CLI/YANG model Enhancements](#CLIYANGmodelEnhancements) - * 1.10.2. [Config DB Enhancements](#ConfigDBEnhancements) - * 1.10.3. [Secure Password Table Schema](#SecurePasswordTableSchema) + * 1.10.1. [PASSWH configDB table](#PASSWHconfigDBtable) + * 1.10.2. [ConfigDB schemas](#ConfigDBschemas) + * 1.10.3. [CLI/YANG model Enhancements](#CLIYANGmodelEnhancements) + * 1.10.4. [Config DB Enhancements](#ConfigDBEnhancements) * 1.11. [Warmboot and Fastboot Design Impact](#WarmbootandFastbootDesignImpact) * 1.12. [Restrictions/Limitations](#RestrictionsLimitations) * 1.13. [Test Plan](#TestPlan) - * 1.13.1. [Setups](#Setups) - * 1.13.2. [CLI configurational tests](#CLIconfigurationaltests) - * 1.13.3. [Precondition:](#Precondition:) - * 1.13.4. [Case 3: check secure password age (expiration) and warning configuration](#Case3:checksecurepasswordageexpirationandwarningconfiguration) - * 1.13.5. [Case 4 – sanity test](#Case4sanitytest) - * 1.13.6. [Negative cases](#Negativecases) - * 1.13.7. [Case 1: check basic configuration – bad flow with invalid input](#Case1:checkbasicconfigurationbadflowwithinvalidinput) - * 1.13.8. [Test Open Issues](#TestOpenIssues) + * 1.13.1. [Unit Test cases](#UnitTestcases) + * 1.13.2. [System Test cases](#SystemTestcases) * 1.14. [3rd Party Components](#rdPartyComponents) * 1.14.1. [pam-cracklib](#pam-cracklib) - * 1.14.2. [PW Age](#PWAge) + * 1.14.2. [PW Age/History](#PWAgeHistory) * 1.14.3. [PW History](#PWHistory) * 1. [Table of Content](#TableofContent) @@ -42,17 +42,17 @@ -### 1.1. Revision +### 1.1. Revision Rev 0.1 -### 1.2. Scope +### 1.2. Scope This password hardening hld doc described the requirements, arcquitecture and configuration details of password hardening feature in switches Sonic OS based. -### 1.3. Definitions/Abbreviations +### 1.3. Definitions/Abbreviations PW - password SPASSWD - secure password daemon -### 1.4. Overview +### 1.4. Overview Password Hardening, a user password is the key credential used in order to verify the user accessing the switch and acts as the first line of defense in regards of securing the switch. The complexity of the password, it's replacement capabilities and change frequency define the security level of the first perimeter of the switch. @@ -65,18 +65,18 @@ Therefore - in order to further improve and harden the switch - a secure mechani | PW Aging | The PW should have an expiration date, after which the user is required to change the PW

A warning to change the PW should be presented to the user a fixed time before the expiration date arrives. This warning should appear in every login so long as the PW expiration time <= warning time. |The user should be able to configure the expiration time of the PW. The user will be able to configure "no aging" for the PW

The user should be able to configure the amount of days to present the warning before the PW expires | PW age time is to be between 1 to 365 days (default 180)

PW warning show is to be between 1 to 30 days (default 15) | PW constraints | The PW class represents the possible characters comprising the PW. There are 4 character classes that can make up the PW:small characters, big characters, numbers and special chars presented on a standard keyboard

The account name and PW need to be different

The new PW is to be different from current PW|The user should be able to define which characters classes are required for the PW out of the 4 provided



The user will be able to enable or disable this feature|Legal special characters `~!@#$%^&*()-_=+\|[{}];:',<.>/? and white space



An error will be shown to the user if it tries to set the same PW as the username



default - enable, default remember last 10 password -### 1.6. Architecture Design +### 1.6. Architecture Design Arc design diagram\ ![passh_arc_sonic](passh_arc_sonic.drawio.png) (flow description in the chapter below) -### 1.7. High-Level Design +### 1.7. High-Level Design In this section we will present the design (as thorough as possible) for the secure PW implementation. User password as explained before is the first line defence, in order to support it according the requirement section and user preferences, the secure password feature need a strengh-checking for password. - + The feature will use 2 linux libs: pam-cracklib, chage and pam_pwhistory.so pam-cracklib: This module can be plugged into the password stack of a given application to provide some plug-in strength-checking for passwords. @@ -98,7 +98,7 @@ See linux 3d party component chapter for more description #### 1.7.1. Flow description: Users by using Switch CLI will set new password/password configuration (see PW options below), the input will be saved in CONF_DB in PASSW_CONF_TABLE.\ -The daemon call PASSHD (password hardening daemon) listen to changes, parse the inputs and set the configuration to kernel by using pam-cracklib ,chage, pwhistory linux libs. +The daemon call PASSHD (password hardening daemon) listen to changes, parse the inputs and set the configuration to kernel by using pam-cracklib ,chage, pwhistory linux libs. After that, it will save the configuration and results in APPL_DB in PASSW_CONF_TABLE. Note: @@ -107,7 +107,7 @@ The table PASSW_CONF_TABLE should reduce time consuming when users need to read #### 1.7.2. Password Hardening Constrains The PW Hardening features will be support different options by encapsulate cracklib, chage and pwhistory options according the constrains definitions below. -##### PW enable +##### PW enable Enable/Disable password hardening feature @@ -207,7 +207,7 @@ This feature will be disabled by default in the compilation stage, its meaning t In addition, the feature will have CLI as a "plugin", meaning that when the feature is not compiled will be not appear in the CLI of the switch, and vice versa. #### 1.8.2. dependencies -Service dependencies: DB container & INIT_CONF. +Service dependencies: DB container & INIT_CONF. Description: Password Hardening Daemon, the service that triggers this daemon, should start after SWSS & DB containers start. @@ -235,7 +235,7 @@ In case the user decides to compile the feature. The password hardening daemon w Note: This approach can support reset of the system, because the daemon can automatically can verify if he should be awake or not. -### 1.9. SAI API +### 1.9. SAI API no changed. ### 1.10. Configuration and management @@ -262,25 +262,24 @@ Note: similar table for PASSWH_STATUS in APPL_DB ``` ; Defines schema for PASSWH configuration attributes (PASSWH table & PASSW_STATUS table have same schema) -key = PASSWH:name ;password hardening configuration +key = PASSWH:name ;password hardening configuration ; field = value -FEATURE_ENABLE = "True" / "False" ; Feature feature enable/disable -EXPIRATION = year ; password expiration 1 year in days units -year = 4DIGIT -EXPIRATION_WARNING = month ; password expiration warning 1 year in days units -month = 2DIGIT -PASSW_HISTORY = 2*DIGIT ; number of old password to be stored (0-99) -LEN_MIN = 2*DIGIT ; max characters in password (0-32 chars) -LEN_MAX = 2*DIGIT ; min characters in password (64-80 chars) -USERNAME_PASSW_MATCH = "True" / "False" -LOWER_CLASS = "True" / "False" -UPPER_CLASS = "True" / "False" -DIGITS_CLASS = "True" / "False" -SPECIAL_CLASS = "True" / "False" +FEATURE_ENABLE = "True" / "False" ; Feature feature enable/disable +EXPIRATION = year ; password expiration 1 year in days units +year = 4DIGIT +EXPIRATION_WARNING = month ; password expiration warning 1 year in days units +month = 2DIGIT +PASSW_HISTORY = 2*DIGIT ; number of old password to be stored (0-99) +LEN_MIN = 2*DIGIT ; max characters in password (0-32 chars) +LEN_MAX = 2*DIGIT ; min characters in password (64-80 chars) +USERNAME_PASSW_MATCH = "True" / "False" +LOWER_CLASS = "True" / "False" +UPPER_CLASS = "True" / "False" +DIGITS_CLASS = "True" / "False" +SPECIAL_CLASS = "True" / "False" ``` - #### 1.10.3. CLI/YANG model Enhancements ```yang //filename: sonic-passw.yang @@ -369,7 +368,7 @@ module sonic-passwh { ``` ##### Config CLI -###### PW enable +###### PW enable Set configuration: ``` @@ -392,7 +391,7 @@ None - Meaning no required classes. lower- lowerLowercase Characters -upper - Uppercase +upper - Uppercase digit - Numbers @@ -406,10 +405,10 @@ The CLI command to configure the PW class type will be along the following lines Set configuration: ``` -config passwh complexity-class -Values in every position are boolean, for example: +config passwh complexity-class +Values in every position are boolean, for example: -config passwh complexity-class False False True True +config passwh complexity-class False False True True ``` Note: Meaning: no must use of lower, no must use of upper, must use digit, must use special characters @@ -433,8 +432,8 @@ Set configuration: ``` config passwh age expiration ``` - -Notes: Where age is in days and between 1 and 365 days (default 180). + +Notes: Where age is in days and between 1 and 365 days (default 180). * PW Age Change Warning Set configuration: @@ -465,17 +464,17 @@ Show command should be extended in order to add "passwh" alias: ========================================== admin@sonic:~$ show passwh PASSWORD HARDENING -Policies status -------------------- ------------ +Policies Status +------------------- ------------ feature state enable -expiration 30 days +expiration 30 days expiration warning 10 days -history 4 -min length 30 -max length 15 -username passw match True -lower class True -upper class True +history 4 +min length 30 +max length 15 +username passw match True +lower class True +upper class True digit class True special class True ========================================== @@ -491,12 +490,12 @@ The ConfigDB will be extended with next objects: ```json { "PASSWH": { - "enable": "True", // enable/disable the feature - "expiration": "30", // days unit - "expiration_warning": "10", //days unit - "history": "10", // num of old password that the system will recorded + "enable": "True", + "expiration": "30", + "expiration_warning": "10", + "history": "10", "len_max": "30", - "len_min": "15", // num of min characters in a password + "len_min": "15", "username_passw_match": "True", "lower class": "True", "upper class": "True", @@ -510,12 +509,12 @@ The AppDB will be extended with table PASSW_STATUS with similar objects than PAS ```json { "PASSWH_STATUS": { - "enable": "True", // enable/disable the feature - "expiration": "30", // days unit - "expiration_warning": "10", //days unit - "history": "10", // num of old password that the system will recorded + "enable": "True", + "expiration": "30", + "expiration_warning": "10", + "history": "10", "len_max": "30", - "len_min": "15", // num of min characters in a password + "len_min": "15", "username_passw_match": "True", "lower class": "True", "upper class": "True", @@ -534,7 +533,7 @@ the main difference is that other applications read from APPL_DB, and not from C ### 1.11. Warmboot and Fastboot Design Impact Not relevant. -### 1.12. Restrictions/Limitations +### 1.12. Restrictions/Limitations The secure password feature is not supported on remote AAA. LDAP/Radius/Tacacs is under customer responsibility. @@ -560,7 +559,7 @@ LDAP/Radius/Tacacs is under customer responsibility. - Configure complexity-class password with random false values - Configure history password with random false values -##### Notes: +##### Notes: - After creating a new policy is necessary to set a new password to a user to verify that the policy match the configured. - Valid values: could be random values from valid ranges. - The set configuration should be validate using the show command and also should be test from the APPL_DB. @@ -691,7 +690,7 @@ Set the number of days of warning before a password change is required. The WARN If none of the options are selected, chage operates in an interactive fashion, prompting the user with the current values for all of the fields. Enter the new value to change the field, or leave the line blank to use the current value. The current value is displayed between a pair of [ ] marks. Notes: If we want to do "age" configuration globally and not per user, it necessary to modify this file: /etc/login.defs, example: - + PASS_MAX_DAYS 90 PASS_WARN_AGE 7 @@ -745,14 +744,14 @@ An example password section would be: #%PAM-1.0 password required pam_pwhistory.so password required pam_unix.so use_authtok - + In combination with pam_cracklib: #%PAM-1.0 password required pam_cracklib.so retry=3 password required pam_pwhistory.so use_authtok password required pam_unix.so use_authtok - + ##### FILES File with password history From 3aa7fe72e65857e90d82f7f8d0f8ed972928d83f Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Wed, 10 Nov 2021 11:29:07 +0200 Subject: [PATCH 08/16] add more descriptions and fix Yang model syntax --- doc/passw_hardening/hld_password_hardening.md | 173 ++++++++++-------- doc/passw_hardening/sonic-passwh.yang | 70 ++++--- 2 files changed, 138 insertions(+), 105 deletions(-) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index 038d0295290..e4ef9e0751d 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -26,13 +26,14 @@ * 1.10.4. [Config DB Enhancements](#ConfigDBEnhancements) * 1.11. [Warmboot and Fastboot Design Impact](#WarmbootandFastbootDesignImpact) * 1.12. [Restrictions/Limitations](#RestrictionsLimitations) - * 1.13. [Test Plan](#TestPlan) - * 1.13.1. [Unit Test cases](#UnitTestcases) - * 1.13.2. [System Test cases](#SystemTestcases) - * 1.14. [3rd Party Components](#rdPartyComponents) - * 1.14.1. [pam-cracklib](#pam-cracklib) - * 1.14.2. [PW Age/History](#PWAgeHistory) - * 1.14.3. [PW History](#PWHistory) + * 1.13. [Upgrade Flow](#UpgradeFlow) + * 1.14. [Test Plan](#TestPlan) + * 1.14.1. [Unit Test cases](#UnitTestcases) + * 1.14.2. [System Test cases](#SystemTestcases) + * 1.15. [3rd Party Components](#rdPartyComponents) + * 1.15.1. [pam-cracklib](#pam-cracklib) + * 1.15.2. [PW Age/History](#PWAgeHistory) + * 1.15.3. [PW History](#PWHistory) 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 Date: Wed, 12 Jan 2022 15:24:46 +0200 Subject: [PATCH 14/16] according the community review decision: modified init flow defaults in yang model and HLD, add bash example using expiration time --- doc/passw_hardening/hld_password_hardening.md | 46 ++++++++++++++----- doc/passw_hardening/sonic-passwh.yang | 12 ++--- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index 056457e9b9a..ceb736f5c31 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -189,6 +189,30 @@ For implement the "aging" we need to change the /etc/login.def file and set max For read the information per user we will use the "chage" library. In addition, when we change the file /etc/login.def its change globally by only new users, so basically for change existing users expired day we need to iterate every one of them using the "chage" lib. +See the example below regarding global expiration time and warning time: + + # /etc/login.def + # Password aging controls: + # + # PASS_MAX_DAYS Maximum number of days a password may be used. + # PASS_MIN_DAYS Minimum number of days allowed between password changes. + # PASS_WARN_AGE Number of days warning given before a password expires. + # + PASS_MAX_DAYS 1 + PASS_MIN_DAYS 0 + PASS_WARN_AGE 7 + +As a result of the changes above, new users will have an expiration time of 1 day, so warning time notification will be prompt in the terminal: + + root@arc-switch1004:/home/admin# adduser test_user1 + root@arc-switch1004:/home/admin# su test_user1 + Warning: your password will expire in 1 day + +Regaring the policy when expiration time end (PASS_MAX_DAYS): + +The maximum number of days a password may be used. If the +password is older than this, a password change will be +forced. In other words, the user remained block until he update a new password. ##### PW username-match By enabling this feature, the user will not be permitted to set the same username & password @@ -207,15 +231,15 @@ For saving password with sha512, need to modify the /etc/pam.d/system-auth-a fil ### 1.8. Init Flow #### 1.8.1. Compilation -This feature will be disabled by default in the compilation stage, this means that it will be not compiled and will be added only when the user specifically adds the relevant compilation flag "INCLUDE_PASSWH" in sonic-buildimage/rules/config file. +This feature will be enabled by default in the compilation stage, this means that it will be compiled, and will be not compiled only when the user specifically adds the relevant compilation flag "INCLUDE_PASSWH=n" in sonic-buildimage/rules/config file. In addition, the feature will have CLI as a "plugin", meaning that when the feature is not compiled will be not appear in the CLI of the switch, and vice versa. Feature enable details: -If the user added the compilation flag to the image, a user can still enable or disable this feature. -By default if the feature was compiled, the feature status will be enabled, meaning that the switch will boot with the feature enable. -the enable default configuration can be founded in init_cfg.json.j2 file. -In case, the user want to disable the feature it can be done by using the Sonic CLI (details in CLI chapter). +when compilation flag is enabled(default value), users can still enable or disable this feature in runtime. +By default if the feature was compiled, the feature status will be disabled, meaning that the switch will boot with the feature compiled, but disable. +the disable default configuration can be founded in init_cfg.json.j2 file. +In case, the user want to enable the feature it can be done by using the Sonic CLI (details in CLI chapter). #### 1.8.2. Dependencies Service dependencies: same dependencies as HOSTCFGD, INIT_CONF and NTP service. @@ -316,7 +340,7 @@ module sonic-passwh { leaf state { description "state of the feature"; type feature_state; - default "enabled"; + default "disabled"; } leaf expiration { description "expiration time (days unit)"; @@ -355,27 +379,27 @@ module sonic-passwh { } leaf username_passw_match{ description "username password match"; - default "true"; + default true; type boolean; } leaf lower_class{ description "password lower chars policy"; - default "true"; + default true; type boolean; } leaf upper_class{ description "password upper chars policy"; - default "true"; + default true; type boolean; } leaf digits_class{ description "password digits chars policy"; - default "true"; + default true; type boolean; } leaf special_class{ description "password special chars policy"; - default "true"; + default true; type boolean; } }/*container policies */ diff --git a/doc/passw_hardening/sonic-passwh.yang b/doc/passw_hardening/sonic-passwh.yang index 2cd24f3f6cf..273ad4d09a5 100644 --- a/doc/passw_hardening/sonic-passwh.yang +++ b/doc/passw_hardening/sonic-passwh.yang @@ -23,7 +23,7 @@ module sonic-passwh { leaf state { description "state of the feature"; type feature_state; - default "enabled"; + default "disabled"; } leaf expiration { description "expiration time (days unit)"; @@ -62,27 +62,27 @@ module sonic-passwh { } leaf username_passw_match{ description "username password match"; - default "true"; + default true; type boolean; } leaf lower_class{ description "password lower chars policy"; - default "true"; + default true; type boolean; } leaf upper_class{ description "password upper chars policy"; - default "true"; + default true; type boolean; } leaf digits_class{ description "password digits chars policy"; - default "true"; + default true; type boolean; } leaf special_class{ description "password special chars policy"; - default "true"; + default true; type boolean; } }/*container policies */ From 089b2dd5d58339597606eb96365a4686a1997849 Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Wed, 19 Jan 2022 10:27:48 +0200 Subject: [PATCH 15/16] change name of history field to history_cnt --- doc/passw_hardening/hld_password_hardening.md | 2 +- doc/passw_hardening/sonic-passwh.yang | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/passw_hardening/hld_password_hardening.md b/doc/passw_hardening/hld_password_hardening.md index ceb736f5c31..a4f36e920e7 100644 --- a/doc/passw_hardening/hld_password_hardening.md +++ b/doc/passw_hardening/hld_password_hardening.md @@ -356,7 +356,7 @@ module sonic-passwh { range 1..30; } } - leaf history { + leaf history_cnt { description "num of old password that the system will recorded"; default 10; type uint8 { diff --git a/doc/passw_hardening/sonic-passwh.yang b/doc/passw_hardening/sonic-passwh.yang index 273ad4d09a5..5a29a4028a7 100644 --- a/doc/passw_hardening/sonic-passwh.yang +++ b/doc/passw_hardening/sonic-passwh.yang @@ -39,7 +39,7 @@ module sonic-passwh { range 1..30; } } - leaf history { + leaf history_cnt { description "num of old password that the system will recorded"; default 10; type uint8 { From 71269e34d0893c46137a86981e75de967c183af2 Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Thu, 20 Jan 2022 10:14:45 +0200 Subject: [PATCH 16/16] fix yang model, move typedef definition in the container --- doc/passw_hardening/sonic-passwh.yang | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/passw_hardening/sonic-passwh.yang b/doc/passw_hardening/sonic-passwh.yang index 5a29a4028a7..b053aa46d02 100644 --- a/doc/passw_hardening/sonic-passwh.yang +++ b/doc/passw_hardening/sonic-passwh.yang @@ -1,22 +1,23 @@ module sonic-passwh { yang-version 1.1; namespace "http://github.com/Azure/sonic-passwh"; - prefix passwh; + prefix passwh; description "PASSWORD HARDENING YANG Module for SONiC OS"; - revision 2021-10-12 { - description - "First Revision"; + revision 2021-10-12 { + description "First Revision"; } - typedef feature_state { - type enumeration { - enum enabled; - enum disabled; - } - } container sonic-passwh { + + typedef feature_state { + type enumeration { + enum enabled; + enum disabled; + } + } + container PASSWH { description "PASSWORD HARDENING part of config_db.json"; container POLICIES {