diff --git a/.github/workflows/ca-password-enforcement-test.yml b/.github/workflows/ca-password-enforcement-test.yml new file mode 100644 index 00000000000..1477cb5788b --- /dev/null +++ b/.github/workflows/ca-password-enforcement-test.yml @@ -0,0 +1,143 @@ +name: CA password enforcement + +on: workflow_call + +env: + DS_IMAGE: ${{ vars.DS_IMAGE || 'quay.io/389ds/dirsrv' }} + +jobs: + # docs/installation/kra/Installing_KRA.md + test: + name: Test + runs-on: ubuntu-latest + env: + SHARED: /tmp/workdir/pki + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Retrieve PKI images + uses: actions/cache@v4 + with: + key: pki-images-${{ github.sha }} + path: pki-images.tar + + - name: Load PKI images + run: docker load --input pki-images.tar + + - name: Create network + run: docker network create example + + - name: Set up DS container + run: | + tests/bin/ds-create.sh \ + --image=${{ env.DS_IMAGE }} \ + --hostname=ds.example.com \ + --password=Secret.123 \ + ds + + - name: Connect DS container to network + run: docker network connect example ds --alias ds.example.com + + - name: Set up PKI container + run: | + tests/bin/runner-init.sh pki + env: + HOSTNAME: pki.example.com + + - name: Connect PKI container to network + run: docker network connect example pki --alias pki.example.com + + - name: Install CA + run: | + docker exec pki pkispawn \ + -f /usr/share/pki/server/examples/installation/ca.cfg \ + -s CA \ + -D pki_ds_url=ldap://ds.example.com:3389 \ + -v + + docker exec pki pki-server cert-find + + - name: Install KRA + run: | + docker exec pki pkispawn \ + -f /usr/share/pki/server/examples/installation/kra.cfg \ + -s KRA \ + -D pki_ds_url=ldap://ds.example.com:3389 \ + -v + + - name: Get CA signing certificate + run: | + docker exec pki pki-server cert-export ca_signing --cert-file ca_signing.crt + + - name: Request profile + run: | + docker exec pki dnf install -y jq + docker exec pki curl --cacert ca_signing.crt -o req.json https://pki.example.com:8443/ca/rest/certrequests/profiles/caServerKeygen_UserCert + docker exec pki jq '.Input[0].Attribute[1].Value|="RSA" | .Input[0].Attribute[2].Value|="2048" | .Input[1].Attribute[0].Value|="test1"' req.json >req.json + + - name: Submit request with good password + run: | + jq '.Input[0].Attribute[0].Value|="k342r09cmIJmklOLIJ,lwerkln234lik-[df"' req.json | \ + docker exec -i pki curl --cacert ca_signing.crt --json @- -o output https://pki.example.com:8443/ca/rest/certrequests + + echo '"pending"' > expected + docker exec pki jq '.entries[0].requestStatus' output > actual + diff expected actual + + - name: Submit request with short password + run: | + jq '.Input[0].Attribute[0].Value|="k342r0"' req.json | \ + docker exec -i pki curl --cacert ca_signing.crt --json @- -o output https://pki.example.com:8443/ca/rest/certrequests + + cat > expected < actual + diff expected actual + + - name: Submit request with numberic password + run: | + jq '.Input[0].Attribute[0].Value|="1234567890246801357938"' req.json | \ + docker exec -i pki curl --cacert ca_signing.crt --json @- -o output https://pki.example.com:8443/ca/rest/certrequests + + cat > expected < actual + diff expected actual + + - name: Disable password policy + run: | + docker exec pki sed -i \ + 's/^policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9,11/policyset.userCertSet.list=1,10,2,3,4,5,6,7,8,9/' \ + /etc/pki/pki-tomcat/ca/profiles/ca/caServerKeygen_UserCert.cfg + + docker exec pki pki-server ca redeploy --wait + + - name: Submit request with minimal password + run: | + jq '.Input[0].Attribute[0].Value|="1"' req.json | \ + docker exec -i pki curl --cacert ca_signing.crt --json @- -o output https://pki.example.com:8443/ca/rest/certrequests + + echo '"pending"' > expected + docker exec pki jq '.entries[0].requestStatus' output > actual + diff expected actual + + - name: Remove KRA + run: docker exec pki pkidestroy -s KRA -v + + - name: Remove CA + run: docker exec pki pkidestroy -s CA -v + + - name: Check CA debug log + if: always() + run: | + docker exec pki find /var/lib/pki/pki-tomcat/logs/ca -name "debug.*" -exec cat {} \; + + - name: Check KRA debug log + if: always() + run: | + docker exec pki find /var/lib/pki/pki-tomcat/logs/kra -name "debug.*" -exec cat {} \; diff --git a/.github/workflows/ca-tests2.yml b/.github/workflows/ca-tests2.yml index 633a318134f..c1fadae9d1e 100644 --- a/.github/workflows/ca-tests2.yml +++ b/.github/workflows/ca-tests2.yml @@ -83,6 +83,11 @@ jobs: needs: build uses: ./.github/workflows/ca-nuxwdog-test.yml + ca-password-enforcment-test: + name: CA password enforcement + needs: build + uses: ./.github/workflows/ca-password-enforcement-test.yml + scep-test: name: SCEP responder needs: build diff --git a/base/server/src/main/resources/UserMessages.properties b/base/server/src/main/resources/UserMessages.properties index 1f7f747de8a..696f89b4932 100644 --- a/base/server/src/main/resources/UserMessages.properties +++ b/base/server/src/main/resources/UserMessages.properties @@ -577,9 +577,9 @@ CMS_PASSWORD_INVALID_LEN=The password must be at least {0} characters CMS_PASSWORD_INVALID_LEN_1=The password must be at least {0} characters CMS_PASSWORD_NON_ALPHANUMERIC=The password contains non-alphanumeric characters CMS_PASSWORD_MISSING_PUNCTUATION=The password requires at least {0} punctuation symbol(s) -CMS_PASSWORD_MISSING_NUMERIC=The password requires at least {0} numeric digit(s), excluding digits in the final position +CMS_PASSWORD_MISSING_NUMERIC=The password requires at least {0} numeric digit(s) CMS_PASSWORD_MISSING_NUMERIC_1=The password requires at least {0} numeric digit(s) -CMS_PASSWORD_MISSING_UPPER_CASE=The password requires at least {0} upper case letter(s), excluding capitals in the initial position +CMS_PASSWORD_MISSING_UPPER_CASE=The password requires at least {0} upper case letter(s) CMS_PASSWORD_MISSING_UPPER_CASE_1=The password requires at least {0} upper case letter(s) CMS_PASSWORD_MISSING_LOWER_CASE=The password requires at least {0} lower case letter(s) CMS_PASSWORD_MISSING_LOWER_CASE_1=The password requires at least {0} lower case letter(s) diff --git a/docs/admin/ServerSideKeygen.adoc b/docs/admin/ServerSideKeygen.adoc index 8d23427a9c5..b789fde229c 100644 --- a/docs/admin/ServerSideKeygen.adoc +++ b/docs/admin/ServerSideKeygen.adoc @@ -84,13 +84,16 @@ output.o1.class_id=pkcs12OutputImpl === Policyset -Password for the generated PKCS12 can be enforced with the follwing policy: +Password for the generated PKCS12 can be enforced with the following policy: -[lietaral] +[literal] policyset.userCertSet.11.constraint.class_id=p12ExportPasswordConstraintImpl policyset.userCertSet.11.constraint.name=PKCS12 Password Constraint policyset.userCertSet.11.constraint.params.password.minSize=20 -policyset.userCertSet.11.constraint.params.password.minCharCategory=2,2,2,2 +policyset.userCertSet.11.constraint.params.password.minUpperLetter=2 +policyset.userCertSet.11.constraint.params.password.minLowerLetter=2 +policyset.userCertSet.11.constraint.params.password.minNumber=2 +policyset.userCertSet.11.constraint.params.password.minSpecialChar=2 policyset.userCertSet.11.constraint.params.password.seqLength=6 policyset.userCertSet.11.constraint.params.password.maxRepeatedChar=3 policyset.userCertSet.11.constraint.params.password.cracklibCheck=false @@ -98,6 +101,26 @@ policyset.userCertSet.11.default.class_id=noDefaultImpl policyset.userCertSet.11.default.name=No Default +This policy allows to set: + +* `password.minSize` - the minimum size for the passwor`d; +* `password.minUpperLetter` - the minimum number of capital letters; +* `password.minLowerLetter` - the minimum number of lower letters; +* `password.minNumber` - the minimum number of digits; +* `password.minSpecialChar` - the minimum number of punctuation characters; +* `password.seqLength` - the size of substring sequence which cannot be repeated; +* `password.maxRepeatedChar` - maximum number of repeating for each character; +* `password.cracklibCheck` - a boolean to request an additional check with *cracklib* (it has to be installed if not present). + + If the constraint does not include specific configuration it will +read the options from the `CS.cfg`. In the case the name is different, +the suffix `password.*` is replaced by `passwordChecker.*`. The +configuration in `CS.cfg` are used for all the passwords but each +profile can overwrite to allow stronger or weaker passwords. + + + + Key type and key size parameters can be configured as exemplified below: [literal] diff --git a/docs/changes/v11.6.0/Server-Changes.adoc b/docs/changes/v11.6.0/Server-Changes.adoc index a347180cd76..dac2c5de287 100644 --- a/docs/changes/v11.6.0/Server-Changes.adoc +++ b/docs/changes/v11.6.0/Server-Changes.adoc @@ -54,8 +54,12 @@ A new policy constraint is defined to enforce the password quality: *p12ExportPa * `password.maxRepeatedChar` - maximum number of repeating for each character; * `password.cracklibCheck` - a boolean to request an additional check with *cracklib* (it has to be installed if not present). -The same options can be configured in the `CS.cfg` replacing -`password.*` with `passwordChecker.*`. The configuration in `CS.cfg` -are used for all the passwords but each profile can overwrite to allow -stronger or weaker passwords. + +These parameter can be configured in each profile using the input +*serverKeygenInputImpl* and the output *pkcs12OutputImpl*. If the +constraint does not include specific configuration it will read the +options from the `CS.cfg`. In the case the name is different, the +suffix `password.*` is replaced by `passwordChecker.*`. The configuration in +`CS.cfg` are used for all the passwords but each profile can overwrite +to allow stronger or weaker passwords.