diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 98729602fb2b..2fa86010d8e5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,14 +25,15 @@ stages: ################################################################################ variables: # synced with Pipeline timeout in GitLab UI - PIPELINE_TIMEOUT: 170m + PIPELINE_TIMEOUT_SCRIPT: 160m + PIPELINE_TIMEOUT_AFTER_SCRIPT: 10m BUILD_PFAPPSERVER_VUE: "yes" PFBUILD_CENTOS_8_IMG: ghcr.io/inverse-inc/packetfence/pfbuild-centos-8 PFBUILD_DEB_BULLSEYE_IMG: ghcr.io/inverse-inc/packetfence/pfbuild-debian-bullseye KANIKO_DEBUG_IMG: gcr.io/kaniko-project/executor:debug + KANIKOBUILD_IMG: ghcr.io/inverse-inc/packetfence/kaniko-build KNK_REGISTRY: ghcr.io KNK_REGISTRY_URL: ${KNK_REGISTRY}/inverse-inc/packetfence - KNK_CACHE: "true" PFBUILD_DEFAULT_DEV_TAG: latest CIDIR: ci CILIBDIR: ci/lib @@ -274,11 +275,38 @@ variables: .build_img_docker_job: stage: build_img script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${PACKERDIR} build_img_docker_pfbuild + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${PACKERDIR} build_img_docker_pfbuild tags: - shell -.build_img_container_job: +.build_img_container_job_dev: + stage: build_img_container + dependencies: [] + image: ${KANIKOBUILD_IMG}:${CI_COMMIT_REF_SLUG} + script: + - /bin/kanikobuild + tags: + - docker + +.build_img_container_job_br_maint: + stage: build_img_container + dependencies: [] + image: ${KANIKOBUILD_IMG}:${CI_COMMIT_REF_SLUG} + script: + - /bin/kanikobuild + tags: + - docker + +.build_img_container_job_rel: + stage: build_img_container + dependencies: [] + image: ${KANIKOBUILD_IMG}:${CI_COMMIT_TAG} + script: + - /bin/kanikobuild + tags: + - docker + +.build_img_container_kanikobuild_job: stage: build_img_container dependencies: [] image: @@ -295,9 +323,9 @@ variables: RESULT_DIR: /var/local/gitlab-runner/vagrant_img BOX_DESC: ${CI_PIPELINE_URL} script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${VAGRANT_IMG_DIR} ${BOX_NAME} + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${VAGRANT_IMG_DIR} ${BOX_NAME} after_script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${VAGRANT_IMG_DIR} clean + - timeout ${PIPELINE_TIMEOUT_AFTER_SCRIPT} make -e -C ${VAGRANT_IMG_DIR} clean tags: - shell - inverse.ca @@ -443,6 +471,7 @@ variables: script: - ./${UPLOAD_DIR}/deploy-artifacts.sh packetfence-release - ./${UPLOAD_DIR}/deploy-artifacts.sh packetfence-export + - ./${UPLOAD_DIR}/deploy-artifacts.sh packetfence-ci-lib tags: - shell @@ -465,8 +494,7 @@ variables: name: sourceforge url: ${SF_ZEN_REPO_URL}/${CI_COMMIT_REF_NAME} after_script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ZENDIR} clean - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ZENDIR} clean_cache + - timeout ${PIPELINE_TIMEOUT_AFTER_SCRIPT} make -e -C ${ZENDIR} clean_all dependencies: [] tags: - shell @@ -476,7 +504,7 @@ variables: environment: name: sourceforge after_script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ISODIR} clean + - timeout ${PIPELINE_TIMEOUT_AFTER_SCRIPT} make -e -C ${ISODIR} clean dependencies: [] tags: - shell @@ -487,9 +515,9 @@ variables: RESULT_DIR: /var/local/gitlab-runner/vagrant_img BOX_DESC: ${CI_PIPELINE_URL} script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${VAGRANT_IMG_DIR} ${BOX_NAME} + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${VAGRANT_IMG_DIR} ${BOX_NAME} after_script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${VAGRANT_IMG_DIR} clean + - timeout ${PIPELINE_TIMEOUT_AFTER_SCRIPT} make -e -C ${VAGRANT_IMG_DIR} clean dependencies: [] tags: - inverse.ca @@ -507,9 +535,9 @@ variables: variables: VAGRANT_COMMON_DOTFILE_PATH: /var/local/gitlab-runner/vagrant/vagrant-common-${CI_COMMIT_REF_SLUG} script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${TESTDIR} MAKE_TARGET=run ${CI_JOB_NAME} + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${TESTDIR} MAKE_TARGET=run ${CI_JOB_NAME} after_script: - - timeout ${PIPELINE_TIMEOUT} ${TESTCIDIR}/clean-test-environment.sh + - timeout ${PIPELINE_TIMEOUT_AFTER_SCRIPT} ${TESTCIDIR}/clean-test-environment.sh ################################################################################ # JOBS @@ -528,17 +556,26 @@ run_pipeline_if_necessary: # BUILD_IMG_CONTAINER JOBS ######################################## # devel +kaniko_dev: + extends: + - .build_img_container_kanikobuild_job + - .build_img_container_devel_rules + variables: + IMAGE_NAME: "kaniko-build" + IMAGE_TAGS: "${CI_COMMIT_REF_SLUG},latest" + pfdeb_dev: extends: - - .build_img_container_job + - .build_img_container_job_dev - .build_img_container_devel_rules + needs: ["kaniko_dev"] variables: IMAGE_NAME: "pfdebian" IMAGE_TAGS: "${CI_COMMIT_REF_SLUG},latest" pfdeb_based_dev: extends: - - .build_img_container_job + - .build_img_container_job_dev - .build_img_container_devel_rules needs: ["pfdeb_dev"] variables: @@ -568,8 +605,9 @@ pfdeb_based_dev: img_dev: extends: - - .build_img_container_job + - .build_img_container_job_dev - .build_img_container_devel_rules + needs: ["kaniko_dev"] variables: IMAGE_TAGS: "${CI_COMMIT_REF_SLUG},latest" parallel: @@ -579,7 +617,7 @@ img_dev: rad_based_dev: extends: - - .build_img_container_job + - .build_img_container_job_dev - .build_img_container_devel_rules needs: ["pfdeb_based_dev"] variables: @@ -594,17 +632,26 @@ rad_based_dev: - "radiusd-eduroam" # branches and maintenance +kaniko_br_maint: + extends: + - .build_img_container_kanikobuild_job + - .build_img_container_branches_and_maintenance_rules + variables: + IMAGE_NAME: "kaniko-build" + IMAGE_TAGS: ${CI_COMMIT_REF_SLUG} + pfdeb_br_maint: extends: - - .build_img_container_job + - .build_img_container_job_br_maint - .build_img_container_branches_and_maintenance_rules + needs: ["kaniko_br_maint"] variables: IMAGE_NAME: "pfdebian" IMAGE_TAGS: ${CI_COMMIT_REF_SLUG} pfdeb_based_br_maint: extends: - - .build_img_container_job + - .build_img_container_job_br_maint - .build_img_container_branches_and_maintenance_rules needs: ["pfdeb_br_maint"] variables: @@ -634,8 +681,9 @@ pfdeb_based_br_maint: img_br_maint: extends: - - .build_img_container_job + - .build_img_container_job_br_maint - .build_img_container_branches_and_maintenance_rules + needs: ["kaniko_br_maint"] variables: IMAGE_TAGS: ${CI_COMMIT_REF_SLUG} parallel: @@ -645,7 +693,7 @@ img_br_maint: rad_based_br_maint: extends: - - .build_img_container_job + - .build_img_container_job_br_maint - .build_img_container_branches_and_maintenance_rules needs: ["pfdeb_based_br_maint"] variables: @@ -660,17 +708,26 @@ rad_based_br_maint: - "radiusd-eduroam" # release +kaniko_rel: + extends: + - .build_img_container_kanikobuild_job + - .release_only_rules + variables: + IMAGE_NAME: "kaniko-build" + IMAGE_TAGS: ${CI_COMMIT_TAG} + pfdeb_rel: extends: - - .build_img_container_job + - .build_img_container_job_rel - .release_only_rules + needs: ["kaniko_rel"] variables: IMAGE_NAME: "pfdebian" IMAGE_TAGS: ${CI_COMMIT_TAG} pfdeb_based_rel: extends: - - .build_img_container_job + - .build_img_container_job_rel - .release_only_rules needs: ["pfdeb_rel"] variables: @@ -698,19 +755,20 @@ pfdeb_based_rel: - "proxysql" img_rel: - extends: - - .build_img_container_job - - .release_only_rules - variables: + extends: + - .build_img_container_job_rel + - .release_only_rules + needs: ["kaniko_rel"] + variables: IMAGE_TAGS: ${CI_COMMIT_TAG} - parallel: - matrix: - - IMAGE_NAME: + parallel: + matrix: + - IMAGE_NAME: - "fingerbank-db" rad_based_rel: extends: - - .build_img_container_job + - .build_img_container_job_rel - .release_only_rules needs: ["pfdeb_based_rel"] variables: @@ -1419,13 +1477,13 @@ build_pf_img_zen_devel_branches_and_maintenance: - .build_pf_img_zen_job - .build_pf_img_zen_devel_branches_and_maintenance_rules script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ZENDIR} zen-deb11 + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${ZENDIR} zen-deb11 build_pf_img_zen_release: extends: - .build_pf_img_zen_job script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ZENDIR} zen-deb11 + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${ZENDIR} zen-deb11 # workaround for https://forum.gitlab.com/t/specify-when-at-job-level-with-a-job-that-has-rules/4769 rules: - if: '$CI_COMMIT_TAG' @@ -1440,7 +1498,7 @@ build_pf_img_iso_devel_branches_and_maintenance: environment: url: ${SF_ISO_REPO_URL}/${CI_COMMIT_REF_SLUG} script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ISODIR} iso + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${ISODIR} iso build_pf_img_iso_release: extends: @@ -1450,7 +1508,7 @@ build_pf_img_iso_release: environment: url: ${SF_ISO_REPO_URL}/${CI_COMMIT_TAG} script: - - timeout ${PIPELINE_TIMEOUT} make -e -C ${ISODIR} iso + - timeout ${PIPELINE_TIMEOUT_SCRIPT} make -e -C ${ISODIR} iso # workaround for https://forum.gitlab.com/t/specify-when-at-job-level-with-a-job-that-has-rules/4769 rules: - if: '$CI_COMMIT_TAG' diff --git a/Makefile b/Makefile index 06895265bddd..f4a0c1c5fc56 100644 --- a/Makefile +++ b/Makefile @@ -321,6 +321,20 @@ pfconnector_remote_install: make -C $(SRC_GODIR) pfconnector install -v -m 0755 $(SRC_GODIR)/pfconnector $(DESTDIR)$(PFCONNECTOR_BINDIR)/pfconnector +# install -D will automatically create target directories +# SRC_RELATIVE_CILIBDIR is used to only get relative paths from PF source tree +# $$file in destination of install command contain relative path +.PHONY: ci_lib_install +ci_lib_install: + @echo "create directories under $(DESTDIR)$(CIDIR)" + install -d -m0755 $(DESTDIR)$(CIDIR) + install -d -m0755 $(DESTDIR)$(CILIBDIR) + + @echo "install $(SRC_RELATIVE_CILIBDIR) files" + for file in $(shell find $(SRC_RELATIVE_CILIBDIR) -type f); do \ + install -v -m 0644 $$file -D $(DESTDIR)$(PF_PREFIX)/$$file ; \ + done + # packetfence-export package .PHONY: distclean-packetfence-export distclean-packetfence-export: @@ -358,3 +372,8 @@ material: DESTDIR=result material: mkdir -p $(CURDIR)/$(DESTDIR) perl $(SRC_ADDONSDIR)/dev-helpers/bin/switch_options_table.pl > $(CURDIR)/$(DESTDIR)/material.html + +html/captive-portal/profile-templates/default/logo.png: + mkdir -p html/captive-portal/profile-templates/default + cp html/common/packetfence-cp.png /usr/local/pf/html/captive-portal/profile-templates/default/logo.png + diff --git a/NEWS.asciidoc b/NEWS.asciidoc index 5dd5388b401d..c29b3b9b7a0c 100644 --- a/NEWS.asciidoc +++ b/NEWS.asciidoc @@ -29,8 +29,14 @@ For a list of compatibility related changes see the < ${dst_dir}/${pf_ci_lib_deb_dest_name}" + scp "${src_dir}/${pf_ci_lib_deb_file}" "${dst_dir}/${pf_ci_lib_deb_dest_name}" \ + || die "scp failed" + done +} + ppa_deploy() { # warning: slashs at end of dirs are significant for rsync src_dir="$PUBLIC_DIR/" @@ -185,6 +201,7 @@ case $1 in deb) deb_deploy ;; packetfence-release) packetfence_release_deploy ;; packetfence-export) packetfence_export_deploy ;; + packetfence-ci-lib) packetfence_ci_lib_deploy ;; ppa) ppa_deploy ;; website) website_deploy ;; *) die "Wrong argument" diff --git a/ci/packer/provisionners_pfbuild/requirements.yml b/ci/packer/provisionners_pfbuild/requirements.yml index 04e9ec18f807..edf3b21a9117 100644 --- a/ci/packer/provisionners_pfbuild/requirements.yml +++ b/ci/packer/provisionners_pfbuild/requirements.yml @@ -1,3 +1,4 @@ --- roles: - src: inverse_inc.gitlab_buildpkg_tools + version: v1.3.5 diff --git a/ci/packer/vagrant_img/provisioners/requirements.yml b/ci/packer/vagrant_img/provisioners/requirements.yml index ea5dc9dd6401..ad3e23153c09 100644 --- a/ci/packer/vagrant_img/provisioners/requirements.yml +++ b/ci/packer/vagrant_img/provisioners/requirements.yml @@ -1,6 +1,7 @@ --- roles: - src: inverse_inc.gitlab_buildpkg_tools + version: v1.3.5 - src: geerlingguy.nodejs version: 6.0.0 diff --git a/ci/packer/zen/Makefile b/ci/packer/zen/Makefile index b288fe1c2889..80b3da8c9381 100644 --- a/ci/packer/zen/Makefile +++ b/ci/packer/zen/Makefile @@ -32,6 +32,9 @@ zen: VM_NAME=$(VM_NAME) \ ./build-and-upload.sh +.PHONY: clean_all +clean_all: clean clean_cache + .PHONY: clean clean: rm -rf $(RESULT_DIR) diff --git a/conf/documentation.conf b/conf/documentation.conf index 83586f919981..18346b9b38e3 100644 --- a/conf/documentation.conf +++ b/conf/documentation.conf @@ -1012,6 +1012,17 @@ Comma delimited IPv4 address of other member mysql members - note that this is o the database. EOT +[database_proxysql.status] +type=toggle +options=enabled|disabled + +[database_proxysql.cacert] +type=path +ext=crt + +[database_proxysql.backend] +type=text + [database.unix_socket] type=text description=<= 1.4.1) Description: PacketFence Connector PacketFence Connector files. This package contains all files related to PacketFence Connector. +Package: packetfence-ci-lib +Architecture: all +Description: CI librairies used by PacketFence + PacketFence CI librairies. This package contains all files related to PacketFence CI librairies. + Package: packetfence-pfcmd-suid Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends} diff --git a/debian/packetfence.postinst b/debian/packetfence.postinst index c88ee86c6548..8c3de82e9cf2 100644 --- a/debian/packetfence.postinst +++ b/debian/packetfence.postinst @@ -54,11 +54,15 @@ case "$1" in VERSIONSQL=$(ls pf-schema-* |sort --version-sort -r | head -1) ln -f -s $VERSIONSQL ./pf-schema.sql - #Make ssl certificate cd /usr/local/pf + + #Make ssl certificate make conf/ssl/server.pem chown pf $PACKETFENCE/conf/ssl/server.key + #Make configurable logo in default profile templates + make html/captive-portal/profile-templates/default/logo.png + # Stop packetfence-config during upgrade process to ensure # it is started with latest code if [ "$(/bin/systemctl show -p ActiveState packetfence-config | awk -F '=' '{print $2}')" = "active" ]; then @@ -98,6 +102,9 @@ case "$1" in echo "pf.conf already exists, won't touch it!" fi + mkdir -p /usr/local/pf/html/captive-portal/profile-templates/default + cp /usr/local/pf/html/common/packetfence-cp.png /usr/local/pf/html/captive-portal/profile-templates/default/logo.png + # managing services set +e for service in apache2 snmptrapfmt freeradius apparmor haproxy keepalived redis-server smbd samba winbind nmbd mysql snmpd netdata collectd proxysql; do diff --git a/debian/rules b/debian/rules index e2223d37c591..434c4c98a8ee 100755 --- a/debian/rules +++ b/debian/rules @@ -53,11 +53,11 @@ install: build # Install all except debian and t directory # dir* to exclude directory itself for i in `find * ! -path 'debian/*' ! -path 'debian' ! -path 'docs/*' ! -path 'docs' ! -path 't/*' ! -path 't' ! -path 'lib/pfconfig/*' ! -path 'lib/pfconfig' ! -path 'sbin/pfconfig*' \ - -not -path "addons/full-upgrade*" -not -path "html/common*" -not -path "html/parking*" -type d`; do \ + -not -path "addons/full-upgrade*" -not -path "html/parking*" -type d`; do \ install -d -m0700 $(CURDIR)/debian/packetfence$(PREFIX)/$(NAME)/$$i; \ done for i in `find * ! -path 'debian/*' ! -path 'debian' ! -path 'docs/*' ! -path 'docs' ! -path 't/*' ! -path 't' ! -path 'lib/pfconfig/*' ! -path 'lib/pfconfig' ! -path 'sbin/pfconfig*' \ - -not -path "addons/full-upgrade/*" -not -path "html/common/*" -not -path "html/parking/*" ! -path 'conf/pfconfig.conf*' ! -path 'conf/redis_cache.conf*' ! -type d`; do \ + -not -path "addons/full-upgrade/*" -not -path "html/parking/*" ! -path 'conf/pfconfig.conf*' ! -path 'conf/redis_cache.conf*' ! -type d`; do \ $(INSTALL) $$i $(CURDIR)/debian/packetfence$(PREFIX)/$(NAME)/$$i; \ done @@ -77,6 +77,9 @@ install: build # packetfence-pfconnector-remote package make DESTDIR=$(CURDIR)/debian/packetfence-pfconnector-remote pfconnector_remote_install + # packetfence-ci-lib package + make DESTDIR=$(CURDIR)/debian/packetfence-ci-lib ci_lib_install + # packetfence-config package for i in `find * -path 'lib/pfconfig*' -type d`; do \ install -d -m0700 $(CURDIR)/debian/packetfence-config$(PREFIX)/$(NAME)/$$i; \ @@ -347,6 +350,14 @@ binary-arch: build install # Addon Stress-tester chmod 0755 $(CURDIR)/debian/packetfence$(PREFIX)/$(NAME)/addons/stress-tester/dhcp_test + + # packetfence-ci-lib + chmod 0755 $(CURDIR)/debian/packetfence-ci-lib$(PREFIX)/$(NAME)/ci/lib/build/*.sh + chmod 0755 $(CURDIR)/debian/packetfence-ci-lib$(PREFIX)/$(NAME)/ci/lib/check/*.sh + chmod 0755 $(CURDIR)/debian/packetfence-ci-lib$(PREFIX)/$(NAME)/ci/lib/common/*.sh + chmod 0755 $(CURDIR)/debian/packetfence-ci-lib$(PREFIX)/$(NAME)/ci/lib/release/*.sh + chmod 0755 $(CURDIR)/debian/packetfence-ci-lib$(PREFIX)/$(NAME)/ci/lib/test/*.sh + chmod 0755 $(CURDIR)/debian/packetfence-ci-lib$(PREFIX)/$(NAME)/ci/lib/upload/*.sh # packetfence pkg chmod 0755 $(CURDIR)/debian/packetfence$(PREFIX)/$(NAME)/addons/*.pl chmod 0755 $(CURDIR)/debian/packetfence$(PREFIX)/$(NAME)/addons/*.sh diff --git a/docs/PacketFence_Upgrade_Guide.asciidoc b/docs/PacketFence_Upgrade_Guide.asciidoc index 2724cf48a24a..db628af8a113 100644 --- a/docs/PacketFence_Upgrade_Guide.asciidoc +++ b/docs/PacketFence_Upgrade_Guide.asciidoc @@ -83,6 +83,13 @@ For all PacketFence versions prior to 11.0.0, follow the steps described in the == Apply maintenance patches +=== Important note for cluster environments + +In cluster environments, you need to perform following steps on **one server +at a time**. To avoid multiple moves of the virtual IP addresses, you can start with +nodes which don't own any virtual IP addresses first. You must ensure all +services have been restarted correctly before moving to the next node. + === Disable monit alerts (only if monit is installed) If `monit` is installed and running, shut it down with: @@ -113,6 +120,10 @@ include::common/upgrade_packages.asciidoc[] include::common/new_config_files.asciidoc[] +=== Rebooting after services have been stopped (optional) + +include::common/reboot.asciidoc[] + === Restart PacketFence services include::common/restart.asciidoc[] diff --git a/docs/common/reboot.asciidoc b/docs/common/reboot.asciidoc new file mode 100644 index 000000000000..40fe7e35906b --- /dev/null +++ b/docs/common/reboot.asciidoc @@ -0,0 +1,24 @@ +If you need to reboot a standalone server or a server from a cluster after services +have been stopped, make sure you set the systemd target to `multi-user.target` +before rebooting: + +[source,bash] +---- +systemctl set-default multi-user.target +---- + +This will make sure your services don't start up after the reboot. It's also the case for `packetfence-mariadb` service. + +Set it back to previous target after it boots up: + +.Cluster +[source,bash] +---- +systemctl set-default packetfence-cluster.target +---- + +.Standalone +[source,bash] +---- +systemctl set-default packetfence.target +---- diff --git a/docs/developer/customizing_packetfence.asciidoc b/docs/developer/customizing_packetfence.asciidoc index a92474e19aaf..7141a44de05d 100644 --- a/docs/developer/customizing_packetfence.asciidoc +++ b/docs/developer/customizing_packetfence.asciidoc @@ -44,35 +44,13 @@ Note that you cannot use the full locale in the template name (i.e. `aup_text.en ===== Logo -WARNING: If you perform an upgrade from a 11.X version, these steps have been handled by an upgrade script. +In order to customize the default logo that is shown on the captive portal, go in _Configuration->Policies And Access Control->Connection Profiles->default->Files_. Next, upload your logo at the root of the files. Once it has been uploaded, go in the _Captive Portal_ section of the connection profile and change the 'Logo' field value to `/profile-templates/default/filename-of-your-logo.png`. -In order to display your own logo on captive portal, you need to follow these -steps on your PacketFence server (or on first node of your cluster): +Alternatively, you could also delete the existing `logo.png` in the files, then upload your logo and rename it to `logo.png`. Doing so will not require to alter the value of 'Logo' in the connection profile. -. Upload your logo through SSH in [filename]`/tmp/my_logo.png` -. Run following commands: +You can also have a different logo per connection profile. In order to do so, upload your logo in the appropriate connection profile, then edit it's 'Logo' value to be `/profile-templates/CONNECTION_PROFILE_ID/filename-of-your-logo.png`. -.Standalone and clusters -[source,bash] ----- -mkdir /usr/local/pf/html/captive-portal/profile-templates/default -cp /tmp/my_logo.png /usr/local/pf/html/captive-portal/profile-templates/default/my_logo.png ----- - -.Clusters only -[source,bash] ----- -cat >> /usr/local/pf/conf/cluster-files.txt << EOF -/usr/local/pf/conf/cluster-files.txt -/usr/local/pf/html/captive-portal/profile-templates/default/my_logo.png -EOF -/usr/local/pf/bin/cluster/sync --as-master ----- - -Once done, connect to PacketFence web admin and configure `default` connection -profile (_Configuration -> Policies and Access control -> Connection profiles_) like this: - -* Logo: [filename]`/profile-templates/default/logo.png` +For the best results, your logo size should be approximately 330x75 pixels. ===== CSS diff --git a/docs/installation/linode/linode.asciidoc b/docs/installation/linode/linode.asciidoc index 3cfdaa42d46f..4a1480a994cc 100644 --- a/docs/installation/linode/linode.asciidoc +++ b/docs/installation/linode/linode.asciidoc @@ -135,7 +135,7 @@ PacketFence Connector released with PacketFence 12.0.0 was not packaged. In order to upgrade your PacketFence Connector to a packaged version, you need to run following commands: -[source,bash] +[source,bash,subs="attributes"] ---- echo 'deb http://inverse.ca/downloads/PacketFence/debian/{release_minor} bullseye bullseye' > \ /etc/apt/sources.list.d/packetfence-pfconnector-remote.list @@ -157,7 +157,7 @@ systemctl restart packetfence-pfconnector-remote In order to upgrade PacketFence Connector, you need to run following commands: -[source,bash] +[source,bash,subs="attributes"] ---- echo 'deb http://inverse.ca/downloads/PacketFence/debian/{release_minor} bullseye bullseye' > \ /etc/apt/sources.list.d/packetfence-pfconnector-remote.list diff --git a/go/chisel/main.go b/go/chisel/main.go index 808b688e9eef..2d866cc2ef9e 100644 --- a/go/chisel/main.go +++ b/go/chisel/main.go @@ -412,7 +412,7 @@ func client(args []string) { flags.StringVar(&config.SrcIP, "src-ip", "", "") hostname := flags.String("hostname", "", "") pid := flags.Bool("pid", false, "") - verbose := flags.Bool("v", false, "") + verbose := flags.Bool("v", (strings.ToLower(os.Getenv("LOG_LEVEL")) == "debug"), "") flags.Usage = func() { fmt.Print(clientHelp) os.Exit(0) diff --git a/go/chisel/server/server_handler.go b/go/chisel/server/server_handler.go index d940d18b3294..a2f0d90ae89e 100644 --- a/go/chisel/server/server_handler.go +++ b/go/chisel/server/server_handler.go @@ -197,6 +197,8 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, req *http.Request) { return tunnel.BindRemotes(ctx, serverInbound) }) if user != nil { + l.Infof("Connector %s has just connected to this server", user.Name) + settings.ClearActiveDynReverseConnector(ctx, user.Name) activeTunnels.Store(user.Name, tunnel) res := s.redis.Set(fmt.Sprintf("%s%s", s.redisTunnelsNamespace, user.Name), fmt.Sprintf("%s://%s", s.listenProto, req.Context().Value(http.LocalAddrContextKey).(net.Addr).String()), 0) if res.Err() != nil { diff --git a/go/chisel/share/settings/active_dyn_reverse.go b/go/chisel/share/settings/active_dyn_reverse.go index c5ff0233a1c9..18f3c7b184ee 100644 --- a/go/chisel/share/settings/active_dyn_reverse.go +++ b/go/chisel/share/settings/active_dyn_reverse.go @@ -1,7 +1,12 @@ package settings import ( + "context" + "fmt" + "strings" "sync" + + "github.com/inverse-inc/go-utils/log" ) var ActiveDynReverse = sync.Map{} @@ -19,3 +24,14 @@ func ClearFromActiveDynReverse(r *Remote) bool { }) return cleared } + +func ClearActiveDynReverseConnector(ctx context.Context, id string) { + ActiveDynReverse.Range(func(kInt, v interface{}) bool { + k := kInt.(string) + if strings.HasPrefix(k, id) { + log.LoggerWContext(ctx).Debug(fmt.Sprintf("Clearing %s from ActiveDynReverse", k)) + ActiveDynReverse.Delete(k) + } + return true + }) +} diff --git a/go/cmd/pfacct/pfacct.go b/go/cmd/pfacct/pfacct.go index a9f9c87d6c0f..891dc3f93501 100644 --- a/go/cmd/pfacct/pfacct.go +++ b/go/cmd/pfacct/pfacct.go @@ -5,6 +5,7 @@ import ( "database/sql" "fmt" "net" + "strconv" "time" cache "github.com/fdurand/go-cache" @@ -22,6 +23,8 @@ import ( ) const DefaultTimeDuration = 5 * time.Minute +const DefaultRadiusWorkers = 5 +const DefaultRadiusWorkQueueSize = 1000 type radiusRequest struct { w radius.ResponseWriter @@ -29,7 +32,6 @@ type radiusRequest struct { switchInfo *SwitchInfo status rfc2866.AcctStatusType mac mac.Mac - done chan struct{} } type PfAcct struct { @@ -56,6 +58,8 @@ type PfAcct struct { radiusdAcctEnabled bool AllNetworks bool ProcessBandwidthAcct bool + RadiusWorkers int + RadiusWorkQueueSize int } func NewPfAcct() *PfAcct { @@ -75,7 +79,12 @@ func NewPfAcct() *PfAcct { err = Database.Ping() } - pfAcct := &PfAcct{Db: Database, TimeDuration: DefaultTimeDuration} + pfAcct := &PfAcct{ + Db: Database, + TimeDuration: DefaultTimeDuration, + RadiusWorkers: DefaultRadiusWorkers, + RadiusWorkQueueSize: DefaultRadiusWorkQueueSize, + } pfAcct.SwitchInfoCache = cache.New(5*time.Minute, 10*time.Minute) pfAcct.NodeSessionCache = cache.New(cache.NoExpiration, cache.NoExpiration) pfAcct.AcctSessionCache = cache.New(5*time.Minute, 10*time.Minute) @@ -83,7 +92,7 @@ func NewPfAcct() *PfAcct { pfAcct.RadiusStatements.Setup(pfAcct.Db) pfAcct.SetupConfig(ctx) - pfAcct.radiusRequests = makeRadiusRequests(pfAcct, 5, 10) + pfAcct.radiusRequests = makeRadiusRequests(pfAcct, pfAcct.RadiusWorkers, pfAcct.RadiusWorkQueueSize) pfAcct.AAAClient = jsonrpc2.NewAAAClientFromConfig(ctx) //pfAcct.Dispatcher = NewDispatcher(16, 128) pfAcct.runPing() @@ -154,10 +163,23 @@ func (pfAcct *PfAcct) SetupConfig(ctx context.Context) { var RadiusConfiguration pfconfigdriver.PfConfRadiusConfiguration pfconfigdriver.FetchDecodeSocket(ctx, &RadiusConfiguration) pfAcct.ProcessBandwidthAcct = sharedutils.IsEnabled(RadiusConfiguration.ProcessBandwidthAccounting) + if !pfAcct.ProcessBandwidthAcct { logInfo(ctx, "Not processing bandwidth accounting records. To enable set radius_configuration.process_bandwidth_accounting = enabled") } + if i, err := strconv.ParseInt(RadiusConfiguration.PfacctWorkers, 10, 64); err != nil { + logWarn(ctx, fmt.Sprintf("Invalid number '%s' pfacct_worker defaulting to '%d'", RadiusConfiguration.PfacctWorkers, pfAcct.RadiusWorkers)) + } else { + pfAcct.RadiusWorkers = int(i) + } + + if i, err := strconv.ParseInt(RadiusConfiguration.PfacctWorkQueueSize, 10, 64); err != nil { + logWarn(ctx, fmt.Sprintf("Invalid number '%s' pfacct_work_queue_size defaulting to '%d'", RadiusConfiguration.PfacctWorkQueueSize, pfAcct.RadiusWorkQueueSize)) + } else { + pfAcct.RadiusWorkQueueSize = int(i) + } + localSecret := pfconfigdriver.LocalSecret{} pfconfigdriver.FetchDecodeSocket(ctx, &localSecret) pfAcct.localSecret = localSecret.Element diff --git a/go/cmd/pfacct/radius.go b/go/cmd/pfacct/radius.go index aebe6fe2d1f8..cee18a8604c0 100644 --- a/go/cmd/pfacct/radius.go +++ b/go/cmd/pfacct/radius.go @@ -12,7 +12,9 @@ import ( "time" "github.com/OneOfOne/xxhash" + "github.com/VividCortex/mysqlerr" cache "github.com/fdurand/go-cache" + "github.com/go-sql-driver/mysql" "github.com/inverse-inc/go-radius" "github.com/inverse-inc/go-radius/dictionary" @@ -91,15 +93,16 @@ func (h *PfAcct) HandleAccounting(w radius.ResponseWriter, r *radius.Request) { callingStation := rfc2865.CallingStationID_GetString(r.Packet) mac, _ := mac.NewFromString(callingStation) rr := radiusRequest{ - w: w, r: r, status: status, switchInfo: switchInfo, mac: mac, - done: make(chan struct{}), } h.sendRadiusRequestToQueue(rr) + outPacket := r.Response(radius.CodeAccountingResponse) + rfc2865.ReplyMessage_SetString(outPacket, "Accounting OK") + w.Write(h.AddProxyState(outPacket, r)) // h.handleAccountingRequest(w, r, switchInfo, mac) // h.Dispatcher.SubmitJob(Work(func() { h.handleAccountingRequest(r, switchInfo) })) } @@ -107,18 +110,11 @@ func (h *PfAcct) HandleAccounting(w radius.ResponseWriter, r *radius.Request) { func (h *PfAcct) sendRadiusRequestToQueue(rr radiusRequest) { queueIndex := djb2Hash(rr.mac[:]) % uint64(len(h.radiusRequests)) h.radiusRequests[queueIndex] <- rr - <-rr.done } func (h *PfAcct) handleAccountingRequest(rr radiusRequest) { - r, w, switchInfo, mac, status := rr.r, rr.w, rr.switchInfo, rr.mac, rr.status + r, switchInfo, mac, status := rr.r, rr.switchInfo, rr.mac, rr.status defer h.NewTiming().Send("pfacct.accounting." + rr.status.String()) - outPacket := r.Response(radius.CodeAccountingResponse) - rfc2865.ReplyMessage_SetString(outPacket, "Accounting OK") - defer func() { - w.Write(h.AddProxyState(outPacket, r)) - rr.done <- struct{}{} - }() ctx := r.Context() in_bytes := int64(rfc2866.AcctInputOctets_Get(r.Packet)) out_bytes := int64(rfc2866.AcctOutputOctets_Get(r.Packet)) @@ -586,6 +582,38 @@ func setupStmt(db *sql.DB, stmt **sql.Stmt, sql string) { } } +func isErrorRetryable(err error) bool { + driverErr, ok := err.(*mysql.MySQLError) + if !ok { + return false + } + + return driverErr.Number == mysqlerr.ER_LOCK_DEADLOCK || driverErr.Number == mysqlerr.ER_LOCK_WAIT_TIMEOUT +} + +func tryExecute(retry int, pause time.Duration, stmt *sql.Stmt, args ...interface{}) (sql.Result, error) { + var err error + var res sql.Result + for retry >= 0 { + retry-- + res, err = stmt.Exec(args...) + if err == nil { + break + } + + if isErrorRetryable(err) { + if pause != 0 { + time.Sleep(pause) + } + continue + } + + break + } + + return res, err +} + func (rs *RadiusStatements) Setup(db *sql.DB) { setupStmt(db, &rs.switchLookup, ` SELECT nasname, secret, unique_session_attributes @@ -776,7 +804,10 @@ func (h *PfAcct) InsertBandwidthAccounting(status rfc2866.AcctStatusType, node_i var err error if status == rfc2866.AcctStatusType_Value_Start { h.SetAcctSession(node_id, unique_session, &AcctSession{in_bytes: in_bytes, out_bytes: out_bytes}) - _, err = h.insertBandwidthAccountingStart.Exec( + _, err = tryExecute( + 3, + time.Millisecond*10, + h.insertBandwidthAccountingStart, node_id, mac, unique_session, @@ -794,7 +825,10 @@ func (h *PfAcct) InsertBandwidthAccounting(status rfc2866.AcctStatusType, node_i } h.SetAcctSession(node_id, unique_session, &AcctSession{in_bytes: in_bytes, out_bytes: out_bytes}) - _, err = h.insertBandwidthAccountingUpdate.Exec( + _, err = tryExecute( + 3, + time.Millisecond*10, + h.insertBandwidthAccountingUpdate, node_id, mac, unique_session, diff --git a/go/cmd/pfdhcp/main.go b/go/cmd/pfdhcp/main.go index f189c5af3515..24373e186be9 100644 --- a/go/cmd/pfdhcp/main.go +++ b/go/cmd/pfdhcp/main.go @@ -222,7 +222,7 @@ func main() { http.Handle("/", httpauth.SimpleBasicAuth(webservices.User, webservices.Pass)(router)) srv := &http.Server{ - Addr: "127.0.0.1:22222", + Addr: ":22222", IdleTimeout: 5 * time.Second, Handler: router, } diff --git a/go/go.mod b/go/go.mod index e6b67d0d0d19..ad756b1d61fd 100644 --- a/go/go.mod +++ b/go/go.mod @@ -114,6 +114,7 @@ require ( github.com/Azure/go-autorest/logger v0.2.0 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect + github.com/VividCortex/mysqlerr v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect diff --git a/go/go.sum b/go/go.sum index be73e7fcfec1..17ee679bf4f1 100644 --- a/go/go.sum +++ b/go/go.sum @@ -84,6 +84,8 @@ github.com/Sereal/Sereal v0.0.0-20200729022450-08708a3c86f3/go.mod h1:D0JMgToj/W github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/VividCortex/mysqlerr v1.0.0 h1:5pZ2TZA+YnzPgzBfiUWGqWmKDVNBdrkf9g+DNe1Tiq8= +github.com/VividCortex/mysqlerr v1.0.0/go.mod h1:xERx8E4tBhLvpjzdUyQiSfUxeMcATEQrflDAfXsqcAE= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= diff --git a/go/httpdportalpreview/httpdportalpreview.go b/go/httpdportalpreview/httpdportalpreview.go index 9eefb14cc2a9..059116acc6dd 100644 --- a/go/httpdportalpreview/httpdportalpreview.go +++ b/go/httpdportalpreview/httpdportalpreview.go @@ -6,10 +6,12 @@ import ( "errors" "fmt" "io/ioutil" + "mime" "net" "net/http" "net/http/httputil" "net/url" + "path/filepath" "regexp" "strings" "time" @@ -114,10 +116,21 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (p *Proxy) ServeStatic(r *http.Response) error { apiClient := unifiedapiclient.NewFromConfig(context.Background()) params, _ := getParams(`/config/profile/(?P.*)/preview/(?P.*)`, p.Uri) + file := params["File"] + buffer, _ := apiClient.CallSimpleHtml(p.Ctx, "GET", "/api/v1/config/connection_profile/"+params["Profile"]+"/preview/"+file, "") + ext := filepath.Ext(file) + if strings.HasSuffix(file, ".html") { + return p.RewriteAnswer(r, buffer) + } - buffer, _ := apiClient.CallSimpleHtml(p.Ctx, "GET", "/api/v1/config/connection_profile/"+params["Profile"]+"/preview/"+params["File"], "") + mimeType := mime.TypeByExtension(ext) + if mimeType != "" { + r.Header["Content-Type"] = []string{mimeType} + } - p.RewriteAnswer(r, buffer) + boeuf := bytes.NewBuffer(buffer) + r.Body = ioutil.NopCloser(boeuf) + r.Header["Content-Length"] = []string{fmt.Sprint(boeuf.Len())} return nil } diff --git a/go/pfconfigdriver/structs.go b/go/pfconfigdriver/structs.go index 1e9141dc9ba4..0ced6374fa99 100644 --- a/go/pfconfigdriver/structs.go +++ b/go/pfconfigdriver/structs.go @@ -719,6 +719,8 @@ type PfConfRadiusConfiguration struct { UsernameAttributes []string `json:"username_attributes"` ForwardKeyBalanced string `json:"forward_key_balanced"` ProcessBandwidthAccounting string `json:"process_bandwidth_accounting"` + PfacctWorkers string `json:"pfacct_workers"` + PfacctWorkQueueSize string `json:"pfacct_work_queue_size"` } type Certificate struct { diff --git a/html/pfappserver/lib/pfappserver/Form/Config/Pf.pm b/html/pfappserver/lib/pfappserver/Form/Config/Pf.pm index 0d5541aa0b07..c0d76b315d7b 100644 --- a/html/pfappserver/lib/pfappserver/Form/Config/Pf.pm +++ b/html/pfappserver/lib/pfappserver/Form/Config/Pf.pm @@ -43,6 +43,7 @@ sub field_list { my $list = []; my $section = $self->section; return [] if !defined $section; + push @$list, id => { id => 'id', type => 'Text'}; my $default_pf_config = pf::IniFiles->new(-file => $pf_default_file, -allowempty => 1); my @section_fields = $default_pf_config->Parameters($section); foreach my $name (@section_fields) { @@ -249,7 +250,20 @@ sub field_list { $field->{element_attr} = {'data-placeholder' => 'No selection'}; my @options = ({value => '', label => 'None' }, map { { value => $_, label => $_ } } get_sms_source_ids()); $field->{options} = \@options; - } + }; + $type eq 'path' && do { + my $old_name = $name; + $field->{type} = 'Path'; + push(@$list, $name => $field); + $name .= "_upload"; + $field = { + id => $name, + type => 'PathUpload', + accessor => $old_name, + config_prefix => $doc_section->{ext}, + upload_namespace => $name, + }; + }; } if ($field->{type} eq 'Text') { if (exists $doc_section->{minimum_length}) { diff --git a/html/pfappserver/root/package.json b/html/pfappserver/root/package.json index 5e1746656a47..883db77e4657 100644 --- a/html/pfappserver/root/package.json +++ b/html/pfappserver/root/package.json @@ -1,6 +1,6 @@ { "name": "packetfence-admin", - "version": "12.1.0", + "version": "12.2.0", "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/html/pfappserver/root/src/components/new/BaseButtonUpload.vue b/html/pfappserver/root/src/components/new/BaseButtonUpload.vue index 277a9b25318a..b8a97fdef672 100644 --- a/html/pfappserver/root/src/components/new/BaseButtonUpload.vue +++ b/html/pfappserver/root/src/components/new/BaseButtonUpload.vue @@ -1,13 +1,18 @@ @@ -117,6 +120,7 @@ import { createDebouncer } from 'promised-debounce' import { useDebouncedWatchHandler } from '@/composables/useDebounce' import useEventJail from '@/composables/useEventJail' import i18n from '@/utils/locale' +import { acceptTextMimes } from '../config' import { yup } from '../schema' const defaults = () => ({ @@ -134,12 +138,12 @@ const setup = (props, context) => { value, } = toRefs(props) - const schema = yup.object({ + const schema = computed(() => yup.object({ name: yup.string() .required(i18n.t('File name required.')) - .isFilenameWithExtension(['html', 'mjml']) - .pathNotExists(entries, path, i18n.t('Filename exists.')) - }) + .isFilenameWithContentType(acceptTextMimes) + .fileNotExists(entries.value, path.value, i18n.t('File exists.')) + })) const form = ref(defaults()) const formRef = ref(null) @@ -185,8 +189,8 @@ const setup = (props, context) => { } else { $store.dispatch('$_connection_profiles/getFile', { id: id.value, filename: path.value }).then(response => { - const { content, meta: { not_deletable, not_revertible } = {} } = response - editorContent.value = content + const { content: { message }, meta: { not_deletable, not_revertible } = {} } = response + editorContent.value = atob(message) isDeletable.value = !not_deletable isRevertible.value = !not_revertible }) @@ -206,7 +210,7 @@ const setup = (props, context) => { let params = { id: id.value, filename: path.value.split('/').filter(u => u).join('/'), - content: editorContent.value + content: btoa(editorContent.value) } if (isNew.value) params.filename += `/${form.value.name}` @@ -331,7 +335,7 @@ const setup = (props, context) => { } export default { - name: 'modal-file', + name: 'modal-edit', components, props, setup diff --git a/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/ModalView.vue b/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/ModalView.vue new file mode 100644 index 000000000000..614daf3f36ca --- /dev/null +++ b/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/ModalView.vue @@ -0,0 +1,122 @@ + + diff --git a/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/TheFilesList.vue b/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/TheFilesList.vue index 5b309dca14e0..39b315159564 100644 --- a/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/TheFilesList.vue +++ b/html/pfappserver/root/src/views/Configuration/connectionProfiles/_components/TheFilesList.vue @@ -11,7 +11,7 @@ /> @@ -22,7 +22,7 @@ :disabled="false" > + :name="name" class="nav-icon" /> @@ -32,13 +32,18 @@
+ :name="name" class="nav-icon" /> - - - {{ item.name }} + + + + {{ item.name }}