citrix_workspace: add more features, refactor derivation

In #89806 it has been reported that the final package is missing a lot
of features like support for the self-service GUI and the
config-management.

While working on supporting those components in the Nix-package, I
decided to refactor the package to simplify the entire setup.

This patch changes the following things:

* Binaries and libraries are patched using the `autoPatchelfHook` to
  avoid having unneeded libraries linked (e.g. some programs use gtk2,
  others use gtk3).

* Moved source-declarations into their own file.

* Wrapped `configmgr` and `selfservice` and added those to `$out/bin`.

* Don't mention the old `citrix_receiver`-packages in the manual anymore
  since those packages were removed in 19.09 and are EOLed anyways.

Closes #89806
This commit is contained in:
Maximilian Bosch
2020-07-15 19:10:58 +02:00
parent bfb7ac3d83
commit fa3948a7c5
6 changed files with 289 additions and 286 deletions
@@ -1,232 +1,25 @@
{ stdenv
, lib
, fetchurl
, requireFile
, makeWrapper
, libredirect
, busybox
, file
, makeDesktopItem
, tzdata
, cacert
, dconf
, glib
, gtk2
, atk
, gdk-pixbuf
, cairo
, pango
, gnome3
, xorg
, libpng12
, freetype
, fontconfig
, gtk_engines
, alsaLib
, zlib
, version ? "20.06.0"
}:
{ lib, callPackage }:
# For detailed information about the Citrix source-tarball, please refer to the OEM
# reference guide: https://developer-docs.citrix.com/projects/workspace-app-for-linux-oem-guide/en/latest/
let
versionInfo = let
supportedVersions = {
"19.12.0" = {
major = "19";
minor = "12";
patch = "0";
x64hash = "1si5mkxbgb8m99bkvgc3l80idjfdp0kby6pv47s07nn43dbr1j7a";
x86hash = "07rfp90ksnvr8zv7ix7f0z6a59n48s7bd4kqbzilfwxgs4ddqmcy";
x64suffix = "19";
x86suffix = "19";
homepage = "https://www.citrix.com/downloads/workspace-app/legacy-workspace-app-for-linux/workspace-app-for-linux-1912.html";
};
inherit (callPackage ./sources.nix { }) supportedVersions unsupportedVersions;
mkCitrix = callPackage ./generic.nix { };
"20.04.0" = {
major = "20";
minor = "04";
patch = "0";
x64hash = "E923592216F9541173846F932784E6C062CB09C9E8858219C7489607BF82A0FB";
x86hash = "A2E2E1882723DA6796E68916B3BB2B44DD575A83DEB03CA90A262F6C81B1A53F";
x64suffix = "21";
x86suffix = "21";
homepage = "https://www.citrix.com/de-de/downloads/workspace-app/legacy-workspace-app-for-linux/workspace-app-for-linux-2004.html";
};
toAttrName = x: "citrix_workspace_${builtins.replaceStrings [ "." ] [ "_" ] x}";
"20.06.0" = {
major = "20";
minor = "06";
patch = "0";
x64hash = "1kpfcfg95mpprlca6cccnjlsqbj3xvv77cn3fc5msd304nsi9x1v";
x86hash = "1di29hrimbw3myjnf2nn26a14klidhdwvjqla6yxhwd3s6lil194";
x64suffix = "15";
x86suffix = "15";
homepage = "https://www.citrix.com/de-de/downloads/workspace-app/linux/workspace-app-for-linux-latest.html";
};
};
unsupported = lib.listToAttrs (
map (x: lib.nameValuePair (toAttrName x) (throw ''
Citrix Workspace at version ${x} is not supported anymore!
# The lifespans of Citrix products can be found here:
# https://www.citrix.com/support/product-lifecycle/milestones/receiver.html
deprecatedVersions = let
versions = [ "19.6.0" "19.8.0" "19.10.0" ];
in
lib.listToAttrs
(lib.forEach versions
(v: lib.nameValuePair v (throw ''
Unsupported citrix_workspace version: ${v}
Actively supported releases are listed here:
https://www.citrix.com/en-gb/support/product-lifecycle/milestones/receiver.html
'')) unsupportedVersions
);
Actively supported releases are listed here:
https://www.citrix.com/en-gb/support/product-lifecycle/milestones/receiver.html
'')));
in
deprecatedVersions // supportedVersions;
citrixWorkspaceForVersion = { major, minor, patch, x64hash, x86hash, x64suffix, x86suffix, homepage }:
stdenv.mkDerivation rec {
pname = "citrix-workspace";
version = "${major}.${minor}.${patch}";
inherit homepage;
prefixWithBitness = if stdenv.is64bit then "linuxx64" else "linuxx86";
preferLocalBuild = true;
src = requireFile rec {
name = if stdenv.is64bit then "${prefixWithBitness}-${version}.${x64suffix}.tar.gz" else "${prefixWithBitness}-${version}.${x86suffix}.tar.gz";
sha256 = if stdenv.is64bit then x64hash else x86hash;
message = ''
In order to use Citrix Workspace, you need to comply with the Citrix EULA and download
the ${if stdenv.is64bit then "64-bit" else "32-bit"} binaries, .tar.gz from:
${homepage}
(if you do not find version ${version} there, try at
https://www.citrix.com/downloads/workspace-app/
Once you have downloaded the file, please use the following command and re-run the
installation:
nix-prefetch-url file://\$PWD/${name}
'';
};
dontBuild = true;
sourceRoot = ".";
buildInputs = [
makeWrapper
busybox
file
gtk2
gdk-pixbuf
];
libPath = stdenv.lib.makeLibraryPath [
glib
gtk2
atk
gdk-pixbuf
cairo
pango
dconf
xorg.libX11
xorg.libXext
xorg.libXrender
xorg.libXinerama
xorg.libXfixes
libpng12
zlib
gtk_engines
freetype
fontconfig
alsaLib
stdenv.cc.cc # Fixes: Can not load [..]/opt/citrix-icaclient/lib/ctxh264_fb.so:(null)
];
desktopItem = makeDesktopItem {
name = "wfica";
desktopName = "Citrix Workspace";
genericName = "Citrix Workspace";
exec = "wfica";
icon = "wfica";
comment = "Connect to remote Citrix server";
categories = "GTK;GNOME;X-GNOME-NetworkSettings;Network;";
mimeType = "application/x-ica";
};
installPhase = ''
runHook preInstall
export ICAInstDir="$out/opt/citrix-icaclient"
sed -i \
-e 's,^main_install_menu$,install_ICA_client,g' \
-e 's,^integrate_ICA_client(),alias integrate_ICA_client=true\nintegrate_ICA_client_old(),g' \
-e 's,^ANSWER=""$,ANSWER="$INSTALLER_YES",' \
-e 's,/bin/true,true,g' \
./${prefixWithBitness}/hinst
# Run the installer...
bash ./${prefixWithBitness}/hinst CDROM "`pwd`"
echo "Deleting broken links..."
for link in `find $ICAInstDir -type l `
do
[ -f "$link" ] || rm -v "$link"
done
echo "Expanding certificates..."
# As explained in https://wiki.archlinux.org/index.php/Citrix#Security_Certificates
pushd "$ICAInstDir/keystore/cacerts"
awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert." c ".pem"}' < ${cacert}/etc/ssl/certs/ca-bundle.crt
popd
echo "Patching executables..."
find $ICAInstDir -type f -exec file {} \; |
grep 'ELF.*executable' |
cut -f 1 -d : |
grep -vi '\(.dll\|.so\)$' | # added as a workaround to https://github.com/NixOS/nixpkgs/issues/41729
while read f
do
echo "Patching ELF intrepreter and rpath for $f"
chmod u+w "$f"
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
--set-rpath "$ICAInstDir:$libPath" "$f"
done
echo "Wrapping wfica..."
mkdir "$out/bin"
makeWrapper "$ICAInstDir/wfica" "$out/bin/wfica" \
--add-flags "-icaroot $ICAInstDir" \
--set ICAROOT "$ICAInstDir" \
--set GTK_PATH "${gtk2.out}/lib/gtk-2.0:${gnome3.gnome-themes-extra}/lib/gtk-2.0" \
--set GDK_PIXBUF_MODULE_FILE "$GDK_PIXBUF_MODULE_FILE" \
--set LD_PRELOAD "${libredirect}/lib/libredirect.so" \
--set LD_LIBRARY_PATH "$libPath" \
--set NIX_REDIRECTS "/usr/share/zoneinfo=${tzdata}/share/zoneinfo:/etc/zoneinfo=${tzdata}/share/zoneinfo:/etc/timezone=$ICAInstDir/timezone"
echo "We arbitrarily set the timezone to UTC. No known consequences at this point."
echo UTC > "$ICAInstDir/timezone"
echo "Installing desktop item..."
mkdir -p $out/share/applications
cp ${desktopItem}/share/applications/* $out/share/applications
# We introduce a dependency on the source file so that it need not be redownloaded everytime
echo $src >> "$out/share/workspace_dependencies.pin"
runHook postInstall
'';
meta = with stdenv.lib; {
license = stdenv.lib.licenses.unfree;
inherit homepage;
description = "Citrix Workspace";
platforms = platforms.linux;
maintainers = with maintainers; [ ma27 ];
};
};
in citrixWorkspaceForVersion (lib.getAttr version versionInfo)
supported = lib.mapAttrs' (
attr: versionInfo: lib.nameValuePair (toAttrName attr) (callPackage ./generic.nix versionInfo)
) supportedVersions;
in
supported // unsupported
@@ -0,0 +1,200 @@
{ stdenv, requireFile, makeWrapper, autoPatchelfHook, wrapGAppsHook, which, more
, file, atk, alsaLib, cairo, fontconfig, gdk-pixbuf, glib, gnome3, gtk2-x11, gtk3
, heimdal, krb5, libsoup, libvorbis, speex, openssl, zlib, xorg, pango, gtk2, gstreamer
, gst-plugins-base, gnome2, nss, nspr, gtk_engines, freetype, dconf, libpng12, libxml2
, libjpeg, libredirect, tzdata, cacert, systemd, libcxxabi, libcxx, e2fsprogs, symlinkJoin
, homepage, version, prefix, hash
, extraCerts ? []
}:
let
inherit (stdenv) lib;
openssl' = symlinkJoin {
name = "openssl-backwards-compat";
nativeBuildInputs = [ makeWrapper ];
paths = [ openssl.out ];
postBuild = ''
ln -sf $out/lib/libcrypto.so $out/lib/libcrypto.so.1.0.0
ln -sf $out/lib/libssl.so $out/lib/libssl.so.1.0.0
'';
};
in
stdenv.mkDerivation rec {
pname = "citrix-workspace";
inherit version;
src = requireFile rec {
name = "${prefix}-${version}.tar.gz";
sha256 = hash;
message = ''
In order to use Citrix Workspace, you need to comply with the Citrix EULA and download
the ${if stdenv.is64bit then "64-bit" else "32-bit"} binaries, .tar.gz from:
${homepage}
(if you do not find version ${version} there, try at
https://www.citrix.com/downloads/workspace-app/
Once you have downloaded the file, please use the following command and re-run the
installation:
nix-prefetch-url file://\$PWD/${name}
'';
};
dontBuild = true;
dontConfigure = true;
sourceRoot = ".";
preferLocalBuild = true;
passthru.icaroot = "${placeholder "out"}/opt/citrix-icaclient";
nativeBuildInputs = [
autoPatchelfHook
file
makeWrapper
more
which
wrapGAppsHook
];
buildInputs = [
alsaLib
atk
cairo
dconf
fontconfig
freetype
gdk-pixbuf
gnome2.gtkglext
gnome3.webkitgtk
gst-plugins-base
gstreamer
gtk2
gtk2-x11
gtk3
gtk_engines
heimdal
krb5
libcxx
libcxxabi
libjpeg
libpng12
libsoup
libvorbis
libxml2
nspr
nss
openssl'
pango
speex
systemd.lib
stdenv.cc.cc
xorg.libXaw
xorg.libXmu
xorg.libXScrnSaver
xorg.libXtst
zlib
] ++ lib.optional (lib.versionOlder version "20.04") e2fsprogs;
runtimeDependencies = [
glib
xorg.libX11
xorg.libXScrnSaver
xorg.libXext
xorg.libXfixes
xorg.libXinerama
xorg.libXmu
xorg.libXrender
xorg.libXtst
xorg.libxcb
];
installPhase = let
icaFlag = program:
if (builtins.match "selfservice(.*)" program) != null then "--icaroot"
else "-icaroot";
wrap = program: ''
wrapProgram $out/opt/citrix-icaclient/${program} \
--add-flags "${icaFlag program} $ICAInstDir" \
--set ICAROOT "$ICAInstDir" \
--prefix LD_LIBRARY_PATH : "$ICAInstDir:$ICAInstDir/lib" \
--set LD_PRELOAD "${libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "/usr/share/zoneinfo=${tzdata}/share/zoneinfo:/etc/zoneinfo=${tzdata}/share/zoneinfo:/etc/timezone=$ICAInstDir/timezone"
'';
wrapLink = program: ''
${wrap program}
ln -sf $out/opt/citrix-icaclient/${program} $out/bin/${baseNameOf program}
'';
copyCert = path: ''
cp -v ${path} $out/opt/citrix-icaclient/keystore/cacerts/${baseNameOf path}
'';
mkWrappers = lib.concatMapStringsSep "\n";
toWrap = [ "wfica" "selfservice" "util/configmgr" "util/conncenter" "util/ctx_rehash" ]
++ lib.optional (lib.versionOlder version "20.06") "selfservice_old";
in ''
runHook preInstall
mkdir -p $out/{bin,share/applications}
export ICAInstDir="$out/opt/citrix-icaclient"
export HOME=$(mktemp -d)
# Run upstream installer in the store-path.
sed -i -e 's,^ANSWER="",ANSWER="$INSTALLER_YES",g' -e 's,/bin/true,true,g' ./linuxx64/hinst
${stdenv.shell} linuxx64/hinst CDROM "$(pwd)"
${mkWrappers wrapLink toWrap}
${mkWrappers wrap [ "PrimaryAuthManager" "ServiceRecord" "AuthManagerDaemon" "util/ctxwebhelper" ]}
ln -sf $ICAInstDir/util/storebrowse $out/bin/storebrowse
# As explained in https://wiki.archlinux.org/index.php/Citrix#Security_Certificates
echo "Expanding certificates..."
pushd "$ICAInstDir/keystore/cacerts"
awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert." c ".pem"}' \
< ${cacert}/etc/ssl/certs/ca-bundle.crt
popd
${mkWrappers copyCert extraCerts}
# See https://developer-docs.citrix.com/projects/workspace-app-for-linux-oem-guide/en/latest/reference-information/#library-files
# Those files are fallbacks to support older libwekit.so and libjpeg.so
rm $out/opt/citrix-icaclient/lib/ctxjpeg_fb_8.so
rm $out/opt/citrix-icaclient/lib/UIDialogLibWebKit.so
echo "We arbitrarily set the timezone to UTC. No known consequences at this point."
echo UTC > "$ICAInstDir/timezone"
echo "Copy .desktop files."
cp $out/opt/citrix-icaclient/desktop/* $out/share/applications/
# We introduce a dependency on the source file so that it need not be redownloaded everytime
echo $src >> "$out/share/workspace_dependencies.pin"
runHook postInstall
'';
# Make sure that `autoPatchelfHook` is executed before
# running `ctx_rehash`.
dontAutoPatchelf = true;
postFixup = ''
autoPatchelf -- "$out"
$out/opt/citrix-icaclient/util/ctx_rehash
'';
meta = with lib; {
license = licenses.unfree;
description = "Citrix Workspace";
platforms = platforms.linux;
maintainers = with maintainers; [ ma27 ];
inherit homepage;
};
}
@@ -0,0 +1,58 @@
{ stdenv, lib }:
let
mkVersionInfo = _: { major, minor, patch, x64hash, x86hash, x64suffix, x86suffix, homepage }:
{ inherit homepage;
version = "${major}.${minor}.${patch}.${if stdenv.is64bit then x64suffix else x86suffix}";
prefix = "linuxx${if stdenv.is64bit then "64" else "86"}";
hash = if stdenv.is64bit then x64hash else x86hash;
};
# Attribute-set with all actively supported versions of the Citrix workspace app
# for Linux.
#
# The latest versions can be found at https://www.citrix.com/de-de/downloads/workspace-app/linux/
supportedVersions = lib.mapAttrs mkVersionInfo {
"19.12.0" = {
major = "19";
minor = "12";
patch = "0";
x64hash = "1si5mkxbgb8m99bkvgc3l80idjfdp0kby6pv47s07nn43dbr1j7a";
x86hash = "07rfp90ksnvr8zv7ix7f0z6a59n48s7bd4kqbzilfwxgs4ddqmcy";
x64suffix = "19";
x86suffix = "19";
homepage = "https://www.citrix.com/downloads/workspace-app/legacy-workspace-app-for-linux/workspace-app-for-linux-1912.html";
};
"20.04.0" = {
major = "20";
minor = "04";
patch = "0";
x64hash = "E923592216F9541173846F932784E6C062CB09C9E8858219C7489607BF82A0FB";
x86hash = "A2E2E1882723DA6796E68916B3BB2B44DD575A83DEB03CA90A262F6C81B1A53F";
x64suffix = "21";
x86suffix = "21";
homepage = "https://www.citrix.com/downloads/workspace-app/linux/workspace-app-for-linux-latest.html";
};
"20.06.0" = {
major = "20";
minor = "06";
patch = "0";
x64hash = "1kpfcfg95mpprlca6cccnjlsqbj3xvv77cn3fc5msd304nsi9x1v";
x86hash = "1di29hrimbw3myjnf2nn26a14klidhdwvjqla6yxhwd3s6lil194";
x64suffix = "15";
x86suffix = "15";
homepage = "https://www.citrix.com/de-de/downloads/workspace-app/linux/workspace-app-for-linux-latest.html";
};
};
# Retain attribute-names for abandoned versions of Citrix workspace to
# provide a meaningful error-message if it's attempted to use such an old one.
#
# The lifespans of Citrix products can be found here:
# https://www.citrix.com/support/product-lifecycle/milestones/receiver.html
unsupportedVersions = [ "19.6.0" "19.8.0" "19.10.0" ];
in {
inherit supportedVersions unsupportedVersions;
}
@@ -1,19 +0,0 @@
{ citrix_workspace, extraCerts ? [], symlinkJoin }:
let
mkCertCopy = certPath:
"cp ${certPath} $out/opt/citrix-icaclient/keystore/cacerts/";
in
if builtins.length extraCerts == 0 then citrix_workspace else symlinkJoin {
name = "citrix-with-extra-certs-${citrix_workspace.version}";
paths = [ citrix_workspace ];
postBuild = ''
${builtins.concatStringsSep "\n" (map mkCertCopy extraCerts)}
sed -i -E "s,-icaroot (.+citrix-icaclient),-icaroot $out/opt/citrix-icaclient," $out/bin/wfica
'';
}