Merge pull request #207115 from s1341/init_freeipa
freeipa: init at 4.10.1
This commit is contained in:
commit
ff296a777e
@ -276,6 +276,7 @@
|
||||
./security/doas.nix
|
||||
./security/duosec.nix
|
||||
./security/google_oslogin.nix
|
||||
./security/ipa.nix
|
||||
./security/lock-kernel-modules.nix
|
||||
./security/misc.nix
|
||||
./security/oath.nix
|
||||
|
258
nixos/modules/security/ipa.nix
Normal file
258
nixos/modules/security/ipa.nix
Normal file
@ -0,0 +1,258 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.security.ipa;
|
||||
pyBool = x:
|
||||
if x
|
||||
then "True"
|
||||
else "False";
|
||||
|
||||
ldapConf = pkgs.writeText "ldap.conf" ''
|
||||
# Turning this off breaks GSSAPI used with krb5 when rdns = false
|
||||
SASL_NOCANON on
|
||||
|
||||
URI ldaps://${cfg.server}
|
||||
BASE ${cfg.basedn}
|
||||
TLS_CACERT /etc/ipa/ca.crt
|
||||
'';
|
||||
nssDb =
|
||||
pkgs.runCommand "ipa-nssdb"
|
||||
{
|
||||
nativeBuildInputs = [pkgs.nss.tools];
|
||||
} ''
|
||||
mkdir -p $out
|
||||
certutil -d $out -N --empty-password
|
||||
certutil -d $out -A --empty-password -n "${cfg.realm} IPA CA" -t CT,C,C -i ${cfg.certificate}
|
||||
'';
|
||||
in {
|
||||
options = {
|
||||
security.ipa = {
|
||||
enable = mkEnableOption (lib.mdDoc "FreeIPA domain integration");
|
||||
|
||||
certificate = mkOption {
|
||||
type = types.package;
|
||||
description = lib.mdDoc ''
|
||||
IPA server CA certificate.
|
||||
|
||||
Use `nix-prefetch-url http://$server/ipa/config/ca.crt` to
|
||||
obtain the file and the hash.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
pkgs.fetchurl {
|
||||
url = http://ipa.example.com/ipa/config/ca.crt;
|
||||
sha256 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
example = "example.com";
|
||||
description = lib.mdDoc "Domain of the IPA server.";
|
||||
};
|
||||
|
||||
realm = mkOption {
|
||||
type = types.str;
|
||||
example = "EXAMPLE.COM";
|
||||
description = lib.mdDoc "Kerberos realm.";
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.str;
|
||||
example = "ipa.example.com";
|
||||
description = lib.mdDoc "IPA Server hostname.";
|
||||
};
|
||||
|
||||
basedn = mkOption {
|
||||
type = types.str;
|
||||
example = "dc=example,dc=com";
|
||||
description = lib.mdDoc "Base DN to use when performing LDAP operations.";
|
||||
};
|
||||
|
||||
offlinePasswords = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc "Whether to store offline passwords when the server is down.";
|
||||
};
|
||||
|
||||
cacheCredentials = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc "Whether to cache credentials.";
|
||||
};
|
||||
|
||||
ifpAllowedUids = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = ["root"];
|
||||
description = lib.mdDoc "A list of users allowed to access the ifp dbus interface.";
|
||||
};
|
||||
|
||||
dyndns = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc "Whether to enable FreeIPA automatic hostname updates.";
|
||||
};
|
||||
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
example = "eth0";
|
||||
default = "*";
|
||||
description = lib.mdDoc "Network interface to perform hostname updates through.";
|
||||
};
|
||||
};
|
||||
|
||||
chromiumSupport = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc "Whether to whitelist the FreeIPA domain in Chromium.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !config.krb5.enable;
|
||||
message = "krb5 must be disabled through `krb5.enable` for FreeIPA integration to work.";
|
||||
}
|
||||
{
|
||||
assertion = !config.users.ldap.enable;
|
||||
message = "ldap must be disabled through `users.ldap.enable` for FreeIPA integration to work.";
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [krb5Full freeipa];
|
||||
|
||||
environment.etc = {
|
||||
"ipa/default.conf".text = ''
|
||||
[global]
|
||||
basedn = ${cfg.basedn}
|
||||
realm = ${cfg.realm}
|
||||
domain = ${cfg.domain}
|
||||
server = ${cfg.server}
|
||||
host = ${config.networking.hostName}
|
||||
xmlrpc_uri = https://${cfg.server}/ipa/xml
|
||||
enable_ra = True
|
||||
'';
|
||||
|
||||
"ipa/nssdb".source = nssDb;
|
||||
|
||||
"krb5.conf".text = ''
|
||||
[libdefaults]
|
||||
default_realm = ${cfg.realm}
|
||||
dns_lookup_realm = false
|
||||
dns_lookup_kdc = true
|
||||
rdns = false
|
||||
ticket_lifetime = 24h
|
||||
forwardable = true
|
||||
udp_preference_limit = 0
|
||||
|
||||
[realms]
|
||||
${cfg.realm} = {
|
||||
kdc = ${cfg.server}:88
|
||||
master_kdc = ${cfg.server}:88
|
||||
admin_server = ${cfg.server}:749
|
||||
default_domain = ${cfg.domain}
|
||||
pkinit_anchors = FILE:/etc/ipa/ca.crt
|
||||
}
|
||||
|
||||
[domain_realm]
|
||||
.${cfg.domain} = ${cfg.realm}
|
||||
${cfg.domain} = ${cfg.realm}
|
||||
${cfg.server} = ${cfg.realm}
|
||||
|
||||
[dbmodules]
|
||||
${cfg.realm} = {
|
||||
db_library = ${pkgs.freeipa}/lib/krb5/plugins/kdb/ipadb.so
|
||||
}
|
||||
'';
|
||||
|
||||
"openldap/ldap.conf".source = ldapConf;
|
||||
};
|
||||
|
||||
environment.etc."chromium/policies/managed/freeipa.json" = mkIf cfg.chromiumSupport {
|
||||
text = ''
|
||||
{ "AuthServerWhitelist": "*.${cfg.domain}" }
|
||||
'';
|
||||
};
|
||||
|
||||
system.activationScripts.ipa = stringAfter ["etc"] ''
|
||||
# libcurl requires a hard copy of the certificate
|
||||
if ! ${pkgs.diffutils}/bin/diff ${cfg.certificate} /etc/ipa/ca.crt > /dev/null 2>&1; then
|
||||
rm -f /etc/ipa/ca.crt
|
||||
cp ${cfg.certificate} /etc/ipa/ca.crt
|
||||
fi
|
||||
|
||||
if [ ! -f /etc/krb5.keytab ]; then
|
||||
cat <<EOF
|
||||
|
||||
In order to complete FreeIPA integration, please join the domain by completing the following steps:
|
||||
1. Authenticate as an IPA user authorized to join new hosts, e.g. kinit admin@${cfg.realm}
|
||||
2. Join the domain and obtain the keytab file: ipa-join
|
||||
3. Install the keytab file: sudo install -m 600 krb5.keytab /etc/
|
||||
4. Restart sssd systemd service: sudo systemctl restart sssd
|
||||
|
||||
EOF
|
||||
fi
|
||||
'';
|
||||
|
||||
services.sssd.config = ''
|
||||
[domain/${cfg.domain}]
|
||||
id_provider = ipa
|
||||
auth_provider = ipa
|
||||
access_provider = ipa
|
||||
chpass_provider = ipa
|
||||
|
||||
ipa_domain = ${cfg.domain}
|
||||
ipa_server = _srv_, ${cfg.server}
|
||||
ipa_hostname = ${config.networking.hostName}.${cfg.domain}
|
||||
|
||||
cache_credentials = ${pyBool cfg.cacheCredentials}
|
||||
krb5_store_password_if_offline = ${pyBool cfg.offlinePasswords}
|
||||
${optionalString ((toLower cfg.domain) != (toLower cfg.realm))
|
||||
"krb5_realm = ${cfg.realm}"}
|
||||
|
||||
dyndns_update = ${pyBool cfg.dyndns.enable}
|
||||
dyndns_iface = ${cfg.dyndns.interface}
|
||||
|
||||
ldap_tls_cacert = /etc/ipa/ca.crt
|
||||
ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock
|
||||
|
||||
[sssd]
|
||||
debug_level = 65510
|
||||
services = nss, sudo, pam, ssh, ifp
|
||||
domains = ${cfg.domain}
|
||||
|
||||
[nss]
|
||||
homedir_substring = /home
|
||||
|
||||
[pam]
|
||||
pam_pwd_expiration_warning = 3
|
||||
pam_verbosity = 3
|
||||
|
||||
[sudo]
|
||||
debug_level = 65510
|
||||
|
||||
[autofs]
|
||||
|
||||
[ssh]
|
||||
|
||||
[pac]
|
||||
|
||||
[ifp]
|
||||
user_attributes = +mail, +telephoneNumber, +givenname, +sn, +lock
|
||||
allowed_uids = ${concatStringsSep ", " cfg.ifpAllowedUids}
|
||||
'';
|
||||
|
||||
services.ntp.servers = singleton cfg.server;
|
||||
services.sssd.enable = true;
|
||||
services.ntp.enable = true;
|
||||
|
||||
security.pki.certificateFiles = singleton cfg.certificate;
|
||||
};
|
||||
}
|
24
pkgs/development/compilers/lesscpy/default.nix
Normal file
24
pkgs/development/compilers/lesscpy/default.nix
Normal file
@ -0,0 +1,24 @@
|
||||
{ stdenv, lib, python3Packages }:
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "lesscpy";
|
||||
version = "0.13.0";
|
||||
|
||||
src = python3Packages.fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "1bbjag13kawnjdn7q4flfrkd0a21rgn9ycfqsgfdmg658jsx1ipk";
|
||||
};
|
||||
|
||||
checkInputs = with python3Packages; [ pytestCheckHook ];
|
||||
pythonImportsCheck = [ "lesscpy" ];
|
||||
propagatedBuildInputs = with python3Packages; [ ply six ];
|
||||
|
||||
doCheck = false; # Really weird test failures (`nix-build-python2.css not found`)
|
||||
|
||||
meta = with lib; {
|
||||
description = "Python LESS Compiler";
|
||||
homepage = "https://github.com/lesscpy/lesscpy";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ s1341 ];
|
||||
};
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{ lib, stdenv, fetchurl, pkg-config, perl, bison, bootstrap_cmds
|
||||
, openssl, openldap, libedit, keyutils
|
||||
, openssl, openldap, libedit, keyutils, libverto
|
||||
|
||||
# for passthru.tests
|
||||
, bind
|
||||
@ -14,6 +14,7 @@
|
||||
# This is called "staticOnly" because krb5 does not support
|
||||
# builting both static and shared, see below.
|
||||
, staticOnly ? false
|
||||
, withVerto ? false
|
||||
}:
|
||||
|
||||
# Note: this package is used for bootstrapping fetchurl, and thus
|
||||
@ -39,6 +40,7 @@ stdenv.mkDerivation rec {
|
||||
# krb5's ./configure does not allow passing --enable-shared and --enable-static at the same time.
|
||||
# See https://bbs.archlinux.org/viewtopic.php?pid=1576737#p1576737
|
||||
++ lib.optionals staticOnly [ "--enable-static" "--disable-shared" ]
|
||||
++ lib.optional withVerto "--with-system-verto"
|
||||
++ lib.optional stdenv.isFreeBSD ''WARN_CFLAGS=""''
|
||||
++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform)
|
||||
[ "krb5_cv_attr_constructor_destructor=yes,yes"
|
||||
@ -53,7 +55,8 @@ stdenv.mkDerivation rec {
|
||||
|
||||
buildInputs = [ openssl ]
|
||||
++ lib.optionals (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.libc != "bionic" && !(stdenv.hostPlatform.useLLVM or false)) [ keyutils ]
|
||||
++ lib.optionals (!libOnly) [ openldap libedit ];
|
||||
++ lib.optionals (!libOnly) [ openldap libedit ]
|
||||
++ lib.optionals withVerto [ libverto ];
|
||||
|
||||
sourceRoot = "krb5-${version}/src";
|
||||
|
||||
|
23
pkgs/development/python-modules/dogtag-pki/default.nix
Normal file
23
pkgs/development/python-modules/dogtag-pki/default.nix
Normal file
@ -0,0 +1,23 @@
|
||||
{ stdenv, lib, fetchPypi, buildPythonPackage, cryptography,
|
||||
ldap, requests, six }:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "dogtag-pki";
|
||||
version = "11.2.1";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-rQSnQPNYr5SyeNbKoFAbnGb2X/8utrfWLa8gu93hy2w=";
|
||||
};
|
||||
|
||||
buildInputs = [ cryptography ldap ];
|
||||
pythonImportsCheck = [ "pki" ];
|
||||
propagatedBuildInputs = [ requests six ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "An enterprise-class Certificate Authority";
|
||||
homepage = "https://github.com/dogtagpki/pki";
|
||||
license = licenses.gpl2;
|
||||
maintainers = with maintainers; [ s1341 ];
|
||||
};
|
||||
}
|
27
pkgs/development/python-modules/yubico/default.nix
Normal file
27
pkgs/development/python-modules/yubico/default.nix
Normal file
@ -0,0 +1,27 @@
|
||||
{ stdenv, lib, buildPythonPackage, fetchPypi, pytestCheckHook, pyusb }:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "python-yubico";
|
||||
version = "1.3.2";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "1gd3an1cdcq328nr1c9ijrsf32v0crv6dgq7knld8m9cadj517c7";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ pyusb ];
|
||||
|
||||
checkInputs = [ pytestCheckHook ];
|
||||
pythonImportsCheck = [ "yubico" ];
|
||||
|
||||
disabledTests = [
|
||||
"usb" # requires a physical yubikey to test
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Python code to talk to YubiKeys";
|
||||
homepage = "https://github.com/Yubico/python-yubico";
|
||||
license = licenses.bsd2;
|
||||
maintainers = with maintainers; [ s1341 ];
|
||||
};
|
||||
}
|
171
pkgs/os-specific/linux/freeipa/default.nix
Normal file
171
pkgs/os-specific/linux/freeipa/default.nix
Normal file
@ -0,0 +1,171 @@
|
||||
{ stdenv
|
||||
, lib
|
||||
, fetchurl
|
||||
, pkgconfig
|
||||
, autoconf
|
||||
, automake
|
||||
, kerberos
|
||||
, openldap
|
||||
, popt
|
||||
, sasl
|
||||
, curl
|
||||
, xmlrpc_c
|
||||
, ding-libs
|
||||
, p11-kit
|
||||
, gettext
|
||||
, nspr
|
||||
, nss
|
||||
, _389-ds-base
|
||||
, svrcore
|
||||
, libuuid
|
||||
, talloc
|
||||
, tevent
|
||||
, samba
|
||||
, libunistring
|
||||
, libverto
|
||||
, libpwquality
|
||||
, systemd
|
||||
, python3
|
||||
, bind
|
||||
, sssd
|
||||
, jre
|
||||
, rhino
|
||||
, lesscpy
|
||||
, jansson
|
||||
, runtimeShell
|
||||
}:
|
||||
|
||||
let
|
||||
pathsPy = ./paths.py;
|
||||
|
||||
pythonInputs = with python3.pkgs; [
|
||||
six
|
||||
ldap
|
||||
dns
|
||||
netaddr
|
||||
netifaces
|
||||
gssapi
|
||||
dogtag-pki
|
||||
pyasn1
|
||||
sssd
|
||||
cffi
|
||||
lxml
|
||||
dbus-python
|
||||
cryptography
|
||||
memcached
|
||||
qrcode
|
||||
pyusb
|
||||
yubico
|
||||
setuptools
|
||||
jinja2
|
||||
augeas
|
||||
samba
|
||||
];
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "freeipa";
|
||||
version = "4.10.1";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://releases.pagure.org/freeipa/freeipa-${version}.tar.gz";
|
||||
sha256 = "sha256-q2rQzcBl1tI4/7+hxEwOY9ND86hObe7O7Y9EEH7cUoA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
python3.pkgs.wrapPython
|
||||
jre
|
||||
rhino
|
||||
lesscpy
|
||||
automake
|
||||
autoconf
|
||||
gettext
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
kerberos
|
||||
openldap
|
||||
popt
|
||||
sasl
|
||||
curl
|
||||
xmlrpc_c
|
||||
pkgconfig
|
||||
ding-libs
|
||||
p11-kit
|
||||
python3
|
||||
nspr
|
||||
nss
|
||||
_389-ds-base
|
||||
svrcore
|
||||
libuuid
|
||||
talloc
|
||||
tevent
|
||||
samba
|
||||
libunistring
|
||||
libverto
|
||||
systemd
|
||||
bind
|
||||
libpwquality
|
||||
jansson
|
||||
] ++ pythonInputs;
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs makeapi makeaci install/ui/util
|
||||
|
||||
substituteInPlace ipaplatform/setup.py \
|
||||
--replace 'ipaplatform.debian' 'ipaplatform.nixos'
|
||||
|
||||
substituteInPlace ipasetup.py.in \
|
||||
--replace 'int(v)' 'int(v.replace("post", ""))'
|
||||
|
||||
substituteInPlace client/ipa-join.c \
|
||||
--replace /usr/sbin/ipa-getkeytab $out/bin/ipa-getkeytab
|
||||
|
||||
cp -r ipaplatform/{fedora,nixos}
|
||||
substitute ${pathsPy} ipaplatform/nixos/paths.py \
|
||||
--subst-var out \
|
||||
--subst-var-by bind ${bind.dnsutils} \
|
||||
--subst-var-by curl ${curl} \
|
||||
--subst-var-by kerberos ${kerberos}
|
||||
'';
|
||||
|
||||
NIX_CFLAGS_COMPILE = "-I${_389-ds-base}/include/dirsrv";
|
||||
pythonPath = pythonInputs;
|
||||
|
||||
# Building and installing the server fails with silent Rhino errors, skipping
|
||||
# for now. Need a newer Rhino version.
|
||||
#buildFlags = [ "client" "server" ]
|
||||
|
||||
configureFlags = [
|
||||
"--with-systemdsystemunitdir=$out/lib/systemd/system"
|
||||
"--with-ipaplatform=nixos"
|
||||
"--disable-server"
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
echo "
|
||||
#!${runtimeShell}
|
||||
echo 'ipa-client-install is not available on NixOS. Please see security.ipa, instead.'
|
||||
exit 1
|
||||
" > $out/sbin/ipa-client-install
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
wrapPythonPrograms
|
||||
rm -rf $out/etc/ipa $out/var/lib/ipa-client/sysrestore
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Identity, Policy and Audit system";
|
||||
longDescription = ''
|
||||
IPA is an integrated solution to provide centrally managed Identity (users,
|
||||
hosts, services), Authentication (SSO, 2FA), and Authorization
|
||||
(host access control, SELinux user roles, services). The solution provides
|
||||
features for further integration with Linux based clients (SUDO, automount)
|
||||
and integration with Active Directory based infrastructures (Trusts).
|
||||
'';
|
||||
homepage = "https://www.freeipa.org/";
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = [ maintainers.s1341 ];
|
||||
platforms = platforms.linux;
|
||||
};
|
||||
}
|
13
pkgs/os-specific/linux/freeipa/paths.py
Normal file
13
pkgs/os-specific/linux/freeipa/paths.py
Normal file
@ -0,0 +1,13 @@
|
||||
from ipaplatform.fedora.paths import FedoraPathNamespace
|
||||
|
||||
class NixOSPathNamespace(FedoraPathNamespace):
|
||||
SBIN_IPA_JOIN = "@out@/bin/ipa-join"
|
||||
IPA_GETCERT = "@out@/bin/ipa-getcert"
|
||||
IPA_RMKEYTAB = "@out@/bin/ipa-rmkeytab"
|
||||
IPA_GETKEYTAB = "@out@/bin/ipa-getkeytab"
|
||||
NSUPDATE = "@bind@/bin/nsupdate"
|
||||
BIN_CURL = "@curl@/bin/curl"
|
||||
KINIT = "@kerberos@/bin/kinit"
|
||||
KDESTROY = "@kerberos@/bin/kdestroy"
|
||||
|
||||
paths = NixOSPathNamespace()
|
@ -2432,6 +2432,8 @@ with pkgs;
|
||||
|
||||
krusader = libsForQt5.callPackage ../applications/file-managers/krusader { };
|
||||
|
||||
lesscpy = callPackage ../development/compilers/lesscpy { };
|
||||
|
||||
lf = callPackage ../applications/file-managers/lf { };
|
||||
|
||||
ctpv = callPackage ../applications/file-managers/lf/ctpv.nix { };
|
||||
@ -19989,6 +19991,16 @@ with pkgs;
|
||||
inherit (darwin) autoSignDarwinBinariesHook;
|
||||
};
|
||||
|
||||
freeipa = callPackage ../os-specific/linux/freeipa {
|
||||
kerberos = krb5.override {
|
||||
withVerto = true;
|
||||
};
|
||||
sasl = cyrus_sasl;
|
||||
samba = samba4.override {
|
||||
enableLDAP = true;
|
||||
};
|
||||
};
|
||||
|
||||
freetts = callPackage ../development/libraries/freetts {
|
||||
jdk = jdk8; # TODO: remove override https://github.com/NixOS/nixpkgs/pull/89731
|
||||
};
|
||||
|
@ -2841,6 +2841,8 @@ self: super: with self; {
|
||||
|
||||
dogpile-cache = callPackage ../development/python-modules/dogpile-cache { };
|
||||
|
||||
dogtag-pki = callPackage ../development/python-modules/dogtag-pki { };
|
||||
|
||||
dogtail = callPackage ../development/python-modules/dogtail { };
|
||||
|
||||
doit = callPackage ../development/python-modules/doit { };
|
||||
@ -12830,6 +12832,8 @@ self: super: with self; {
|
||||
|
||||
ytmusicapi = callPackage ../development/python-modules/ytmusicapi { };
|
||||
|
||||
yubico = callPackage ../development/python-modules/yubico { };
|
||||
|
||||
yubico-client = callPackage ../development/python-modules/yubico-client { };
|
||||
|
||||
z3c-checkversions = callPackage ../development/python-modules/z3c-checkversions { };
|
||||
|
Loading…
Reference in New Issue
Block a user