Doublecheck if real FIPS host available in GH actions
Closes https://github.com/keycloak/keycloak/issues/15069
This commit is contained in:
parent
22e256149c
commit
5b626231d9
6 changed files with 142 additions and 15 deletions
6
.github/fake_fips/Makefile
vendored
Normal file
6
.github/fake_fips/Makefile
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
obj-m = fake_fips.o
|
||||||
|
KVERSION = $(shell uname -r)
|
||||||
|
all:
|
||||||
|
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
|
||||||
|
clean:
|
||||||
|
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
|
72
.github/fake_fips/fake_fips.c
vendored
Normal file
72
.github/fake_fips/fake_fips.c
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* https://github.com/torvalds/linux/blob/master/crypto/fips.c
|
||||||
|
* https://pointer-overloading.blogspot.com/2013/09/linux-creating-entry-in-proc-file.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/sysctl.h>
|
||||||
|
|
||||||
|
int fips_enabled = 1;
|
||||||
|
|
||||||
|
static struct ctl_table crypto_sysctl_table[] = {
|
||||||
|
{
|
||||||
|
.procname = "fips_enabled",
|
||||||
|
.data = &fips_enabled,
|
||||||
|
.maxlen = sizeof(int),
|
||||||
|
.mode = 0444,
|
||||||
|
.proc_handler = proc_dointvec
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
static struct ctl_table crypto_dir_table[] = {
|
||||||
|
{
|
||||||
|
.procname = "crypto",
|
||||||
|
.mode = 0555,
|
||||||
|
.child = crypto_sysctl_table
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ctl_table_header *crypto_sysctls;
|
||||||
|
|
||||||
|
static void crypto_proc_fips_init(void)
|
||||||
|
{
|
||||||
|
crypto_sysctls = register_sysctl_table(crypto_dir_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crypto_proc_fips_exit(void)
|
||||||
|
{
|
||||||
|
unregister_sysctl_table(crypto_sysctls);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init fips_init(void)
|
||||||
|
{
|
||||||
|
crypto_proc_fips_init();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit fips_exit(void)
|
||||||
|
{
|
||||||
|
crypto_proc_fips_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
subsys_initcall(fips_init);
|
||||||
|
module_exit(fips_exit);
|
17
.github/scripts/run-fips-it.sh
vendored
Executable file
17
.github/scripts/run-fips-it.sh
vendored
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
dnf install -y java-17-openjdk-devel crypto-policies-scripts
|
||||||
|
fips-mode-setup --enable --no-bootcfg
|
||||||
|
fips-mode-setup --is-enabled
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
STRICT_OPTIONS=""
|
||||||
|
if [ "$1" = "strict" ]; then
|
||||||
|
STRICT_OPTIONS="-Dauth.server.fips.mode=strict -Dauth.server.supported.keystore.types=BCFKS -Dauth.server.keystore.type=bcfks -Dauth.server.supported.rsa.key.sizes=2048,4096"
|
||||||
|
fi
|
||||||
|
echo "STRICT_OPTIONS: $STRICT_OPTIONS"
|
||||||
|
TESTS=`testsuite/integration-arquillian/tests/base/testsuites/suite.sh fips`
|
||||||
|
echo "Tests: $TESTS"
|
||||||
|
export JAVA_HOME=/etc/alternatives/java_sdk_17
|
||||||
|
./mvnw test -Dsurefire.rerunFailingTestsCount=$SUREFIRE_RERUN_FAILING_COUNT -nsu -B -Pauth-server-quarkus,auth-server-fips140-2 -Dcom.redhat.fips=false $STRICT_OPTIONS -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base | misc/log/trimmer.sh
|
15
.github/scripts/run-fips-ut.sh
vendored
Executable file
15
.github/scripts/run-fips-ut.sh
vendored
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
dnf install -y java-17-openjdk-devel crypto-policies-scripts
|
||||||
|
fips-mode-setup --enable --no-bootcfg
|
||||||
|
fips-mode-setup --is-enabled
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "fips.provider.7=XMLDSig" >>/etc/alternatives/java_sdk_17/conf/security/java.security
|
||||||
|
export JAVA_HOME=/etc/alternatives/java_sdk_17
|
||||||
|
./mvnw test -nsu -B -am -pl crypto/default,crypto/fips1402 -Dcom.redhat.fips=true
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
./mvnw test -nsu -B -am -pl crypto/default,crypto/fips1402 -Dcom.redhat.fips=true -Dorg.bouncycastle.fips.approved_only=true
|
31
.github/workflows/ci.yml
vendored
31
.github/workflows/ci.yml
vendored
|
@ -390,15 +390,20 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Fake fips
|
||||||
|
run: |
|
||||||
|
cd .github/fake_fips
|
||||||
|
make
|
||||||
|
sudo insmod fake_fips.ko
|
||||||
|
|
||||||
- id: unit-test-setup
|
- id: unit-test-setup
|
||||||
name: Unit test setup
|
name: Unit test setup
|
||||||
uses: ./.github/actions/unit-test-setup
|
uses: ./.github/actions/unit-test-setup
|
||||||
|
with:
|
||||||
|
jdk-version: 17
|
||||||
|
|
||||||
- name: Run crypto tests (BCFIPS non-approved mode)
|
- name: Run crypto tests
|
||||||
run: ./mvnw test -nsu -B -am -pl crypto/default,crypto/fips1402,crypto/elytron -Dcom.redhat.fips=true
|
run: docker run --rm --workdir /github/workspace -v "${{ github.workspace }}":"/github/workspace" -v "$HOME/.m2":"/root/.m2" registry.access.redhat.com/ubi8/ubi:latest .github/scripts/run-fips-ut.sh
|
||||||
|
|
||||||
- name: Run crypto tests (BCFIPS approved mode)
|
|
||||||
run: ./mvnw test -nsu -B -am -pl crypto/default,crypto/fips1402,crypto/elytron -Dcom.redhat.fips=true -Dorg.bouncycastle.fips.approved_only=true
|
|
||||||
|
|
||||||
- name: Upload JVM Heapdumps
|
- name: Upload JVM Heapdumps
|
||||||
if: always()
|
if: always()
|
||||||
|
@ -424,21 +429,23 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Fake fips
|
||||||
|
run: |
|
||||||
|
cd .github/fake_fips
|
||||||
|
make
|
||||||
|
sudo insmod fake_fips.ko
|
||||||
|
|
||||||
- id: integration-test-setup
|
- id: integration-test-setup
|
||||||
name: Integration test setup
|
name: Integration test setup
|
||||||
uses: ./.github/actions/integration-test-setup
|
uses: ./.github/actions/integration-test-setup
|
||||||
|
with:
|
||||||
|
jdk-version: 17
|
||||||
|
|
||||||
- name: Prepare Quarkus distribution with BCFIPS
|
- name: Prepare Quarkus distribution with BCFIPS
|
||||||
run: ./mvnw install -nsu -B -e -pl testsuite/integration-arquillian/servers/auth-server/quarkus -Pauth-server-quarkus,auth-server-fips140-2
|
run: ./mvnw install -nsu -B -e -pl testsuite/integration-arquillian/servers/auth-server/quarkus -Pauth-server-quarkus,auth-server-fips140-2
|
||||||
|
|
||||||
- name: Run base tests
|
- name: Run base tests
|
||||||
run: |
|
run: docker run --rm --workdir /github/workspace -e "SUREFIRE_RERUN_FAILING_COUNT" -v "${{ github.workspace }}":"/github/workspace" -v "$HOME/.m2":"/root/.m2" registry.access.redhat.com/ubi8/ubi:latest .github/scripts/run-fips-it.sh ${{ matrix.mode }}
|
||||||
declare -A PARAMS
|
|
||||||
PARAMS["non-strict"]=""
|
|
||||||
PARAMS["strict"]="-Dauth.server.fips.mode=strict -Dauth.server.supported.keystore.types=BCFKS -Dauth.server.keystore.type=bcfks -Dauth.server.supported.rsa.key.sizes=2048,4096"
|
|
||||||
TESTS=`testsuite/integration-arquillian/tests/base/testsuites/suite.sh fips`
|
|
||||||
echo "Tests: $TESTS"
|
|
||||||
./mvnw test -Dsurefire.rerunFailingTestsCount=${{ env.SUREFIRE_RERUN_FAILING_COUNT }} -nsu -B -Pauth-server-quarkus,auth-server-fips140-2 ${PARAMS["${{ matrix.mode }}"]} -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base | misc/log/trimmer.sh
|
|
||||||
|
|
||||||
- name: Upload JVM Heapdumps
|
- name: Upload JVM Heapdumps
|
||||||
if: always()
|
if: always()
|
||||||
|
|
|
@ -11,13 +11,14 @@ import org.keycloak.common.profile.ProfileException;
|
||||||
import org.keycloak.common.profile.PropertiesFileProfileConfigResolver;
|
import org.keycloak.common.profile.PropertiesFileProfileConfigResolver;
|
||||||
import org.keycloak.common.profile.PropertiesProfileConfigResolver;
|
import org.keycloak.common.profile.PropertiesProfileConfigResolver;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -69,7 +70,12 @@ public class ProfileTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals(Profile.ProfileName.DEFAULT, profile.getName());
|
Assert.assertEquals(Profile.ProfileName.DEFAULT, profile.getName());
|
||||||
assertEquals(profile.getDisabledFeatures(), Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.DYNAMIC_SCOPES, Profile.Feature.DOCKER, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.MAP_STORAGE, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL);
|
Set<Profile.Feature> disabledFeatutes = new HashSet<>(Arrays.asList(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.DYNAMIC_SCOPES, Profile.Feature.DOCKER, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.MAP_STORAGE, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL));
|
||||||
|
// KERBEROS can be disabled (i.e. FIPS mode disables SunJGSS provider)
|
||||||
|
if (Profile.Feature.KERBEROS.getType() == Profile.Feature.Type.DISABLED_BY_DEFAULT) {
|
||||||
|
disabledFeatutes.add(Profile.Feature.KERBEROS);
|
||||||
|
}
|
||||||
|
assertEquals(profile.getDisabledFeatures(), disabledFeatutes);
|
||||||
assertEquals(profile.getPreviewFeatures(), Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL);
|
assertEquals(profile.getPreviewFeatures(), Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.OPENSHIFT_INTEGRATION, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,8 +232,12 @@ public class ProfileTest {
|
||||||
Assert.assertTrue(Profile.isFeatureEnabled(PREVIEW_FEATURE));
|
Assert.assertTrue(Profile.isFeatureEnabled(PREVIEW_FEATURE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void assertEquals(Set<Profile.Feature> actual, Collection<Profile.Feature> expected) {
|
||||||
|
assertEquals(actual, expected.toArray(new Profile.Feature[0]));
|
||||||
|
}
|
||||||
|
|
||||||
public static void assertEquals(Set<Profile.Feature> actual, Profile.Feature... expected) {
|
public static void assertEquals(Set<Profile.Feature> actual, Profile.Feature... expected) {
|
||||||
Profile.Feature[] a = actual.toArray(new Profile.Feature[actual.size()]);
|
Profile.Feature[] a = actual.toArray(new Profile.Feature[0]);
|
||||||
Arrays.sort(a, new FeatureComparator());
|
Arrays.sort(a, new FeatureComparator());
|
||||||
Arrays.sort(expected, new FeatureComparator());
|
Arrays.sort(expected, new FeatureComparator());
|
||||||
Assert.assertArrayEquals(a, expected);
|
Assert.assertArrayEquals(a, expected);
|
||||||
|
|
Loading…
Reference in a new issue