Skip to content

Commit

Permalink
Use virtual package mechanism for BoringSSL package (#686)
Browse files Browse the repository at this point in the history
* Use virtual package mechanism for BoringSSL package

Why alternative packages are not good
-------------------------------------

Alternative package dependencies are great, but they have several issues
for the use case we need. First of all, 'boolean package dependencies'
are not supported on CentOS 7 which we need to support. RPM >= 4.13 is
required to build *and* install such packages correctly [1].
Unfortunately, CentOS 7 uses RPM 4.11 so we're out of luck here.

[1]: https://rpm.org/user_doc/boolean_dependencies.html

The second issue is that if some other package previously depended on,
say, "libthemis (>= 0.13)", the new "libthemis-boringssl" cannot satisfy
that depenency. It is able to, but the package manager will not allow it
to be installed for it is not "libthemis".

What is the alternative to them? (heh)
--------------------------------

Alternative (boolean) package dependencies may work for our packages
since we make them to, but they won't work for other packages.

In fact, alternative dependencies are not the best solution here. We
would like the BoringSSL flavor to be able to stand in for the OpenSSL
flavor because it provides the same API and ABI. dpkg and RPM have a
mechanism for this -- the "Provides" field in the package specs.

"Provides", "Conflicts", and "Replaces"
---------------------------------------

If BoringSSL package *provides* "libthemis" then it can satify the need
for "libthemis" of any other package, like "libthemis-jni", for example.
Similarly, "libthemis-boringssl-dev" provides "libthemis-dev".

Note, however, that "libthemis" and "libthemis-boringssl" are still
mutually exclusive so they need to conflict with each other. In fact,
all flavors of "libthemis" conflict with each other and the same is true
for the development packages as well.

In addition to that, if we declare them as *replacing* one other, the
package manager will be able to tell that it can remove the old
conflicting package and install an alternative to it, without bothering
the user.

Caveats
-------

FPM discards versioning information from "--provides" arguments. While
RPM does not seem to have any issues with that, dpkg does have issues
which break conflict resolution if the provided versions are not
specificed. We have to insert DEB fields directly to fix this.
Otherwise the users will see the following errors

    dpkg: dependency problems prevent configuration of libthemis-jni:
     libthemis-jni depends on libthemis (>= 0.13.0+xenial); however:
      Package libthemis is not installed.
      Version of libthemis on system, provided by libthemis-boringssl:amd64, is <none>.

    dpkg: error processing package libthemis-jni (--install):
     dependency problems - leaving unconfigured

when installing packages that depend on "libthemis" when it is replaced
by "libthemis-boringssl".

Remaining issues
----------------

Although packages can replace each other, there are still some issues
with that. For example, on Debian I am not able to cleanly replace both
"libthemis" and "libthemis-dev" simultaneously with "libthemis-boringssl"
and "libthemis-boringssl-dev", while it is still to do it one package
at a time, if done in correct order. RPM on the other had is fine.

Also, it is currently possible to install "libthemis-boringssl" and
"libthemis-dev" simultaneously without conflicts. While technically it
still works, this may be surprising for the users, especially if they
try building something with static libraries. It would be nice to
disallow such installation in some way.

* Fix "libthemis" dependencies on some systems

On some systems (e.g., Ubuntu 16.04) the "libssl-dev" package depends
not only on "libsslX.Y.Z", but on other packages too ("zlib1g" in the
casse of Ubuntu). The current spell for finding out the name of the
OpenSSL library package does not take that into account, and this leads
to incorrect command line passed to FPM.

Improve the spell to react only on "libssl" packages, which there should
be only one in the dependency list.
  • Loading branch information
ilammy authored Aug 12, 2020
1 parent bef80bc commit 960f000
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 35 deletions.
8 changes: 4 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ _Code:_
- **Core**

- Include embedded BoringSSL into Soter for convenience ([#681](https://github.com/cossacklabs/themis/pull/681)).
- `make deb` and `make rpm` with `ENGINE=boringssl` will now produce `libthemis-boringssl` packages with embedded BoringSSL ([#683](https://github.com/cossacklabs/themis/pull/683)).
- `make deb` and `make rpm` with `ENGINE=boringssl` will now produce `libthemis-boringssl` packages with embedded BoringSSL ([#683](https://github.com/cossacklabs/themis/pull/683), [#686](https://github.com/cossacklabs/themis/pull/686)).
- Improved compatibility with OpenSSL 1.1.1 ([#684](https://github.com/cossacklabs/themis/pull/684)).
- `secure_session_create()` now allows only EC keys, returning an error for RSA ([#693](https://github.com/cossacklabs/themis/pull/693)).

Expand Down Expand Up @@ -40,17 +40,17 @@ _Code:_
- **Objective-C**

- Updated Objective-C examples (iOS and macOS, Carthage and CocoaPods) to showcase usage of the newest Secure Cell API: generating symmetric keys and using Secure Cell with Passphrase ([#688](https://github.com/cossacklabs/themis/pull/688)).

- **Rust**

- Dropped `libthemis-src` crate support and removed the `vendored` feature. RustThemis wrapper now requires Themis Core to be installed in the system ([#691](https://github.com/cossacklabs/themis/pull/691)).

_Infrastructure:_

- Improved package split making `libthemis` thinner ([#678](https://github.com/cossacklabs/themis/pull/678)).
- Optimized dependencies of `libthemis` DEB and RPM packages ([#682](https://github.com/cossacklabs/themis/pull/682)).
- Optimized dependencies of `libthemis` DEB and RPM packages ([#682](https://github.com/cossacklabs/themis/pull/682), [#686](https://github.com/cossacklabs/themis/pull/686)).
- AndroidThemis is now available on JCenter ([#679](https://github.com/cossacklabs/themis/pull/679)).
- `make deb` and `make rpm` with `ENGINE=boringssl` will now produce `libthemis-boringssl` packages with embedded BoringSSL ([#683](https://github.com/cossacklabs/themis/pull/683)).
- `make deb` and `make rpm` with `ENGINE=boringssl` will now produce `libthemis-boringssl` packages with embedded BoringSSL ([#683](https://github.com/cossacklabs/themis/pull/683), [#686](https://github.com/cossacklabs/themis/pull/686)).
- Build system and tests now respect the `PATH` settings ([#685](https://github.com/cossacklabs/themis/pull/685)).

## [0.13.0](https://github.com/cossacklabs/themis/releases/tag/0.13.0), July 8th 2020
Expand Down
71 changes: 40 additions & 31 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -616,32 +616,47 @@ LICENSE_NAME = "Apache License Version 2.0"

DEB_CODENAME := $(shell lsb_release -cs 2> /dev/null)
DEB_ARCHITECTURE = `dpkg --print-architecture 2>/dev/null`
ifneq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
ifeq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
# fpm has "--provides" option, but it eats package versions when we need to
# preserve them for correct dependency resolution. Insert fields directly.
DEB_DEPENDENCIES += --deb-field "Provides: $(CANONICAL_PACKAGE_NAME) (= $(VERSION)+$(OS_CODENAME))"
DEB_DEPENDENCIES += --conflicts $(CANONICAL_PACKAGE_NAME)
DEB_DEPENDENCIES += --replaces $(CANONICAL_PACKAGE_NAME)
DEB_DEPENDENCIES_DEV += --deb-field "Provides: $(DEB_CANONICAL_DEV_PACKAGE_NAME) (= $(VERSION)+$(OS_CODENAME))"
DEB_DEPENDENCIES_DEV += --conflicts $(DEB_CANONICAL_DEV_PACKAGE_NAME)
DEB_DEPENDENCIES_DEV += --replaces $(DEB_CANONICAL_DEV_PACKAGE_NAME)
else
# If we were using native Debian packaging, dpkg-shlibdeps could supply us with
# accurate dependency information. However, we build packages manually, so we
# use dependencies of "libssl-dev" as a proxy. Typically this is "libssl1.1".
DEB_DEPENDENCIES += --depends $(shell apt-cache depends libssl-dev | grep 'Depends:' | cut -d: -f 2- | tr -d ' ')
endif
DEB_DEPENDENCIES += --conflicts $(OTHER_PACKAGE_NAME)
DEB_DEPENDENCIES_DEV += --depends "$(PACKAGE_NAME) = $(VERSION)+$(OS_CODENAME)"
ifneq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
#
# Example output of "apt-cache depends" (from Ubuntu 16.04):
#
# libssl-dev
# Depends: libssl1.0.0
# Depends: zlib1g-dev
# Recommends: libssl-doc
DEB_DEPENDENCIES += $(shell apt-cache depends libssl-dev | awk '$$1 == "Depends:" && $$2 ~ /^libssl/ { print "--depends", $$2 }' )
DEB_DEPENDENCIES_DEV += --depends libssl-dev
endif
DEB_DEPENDENCIES_DEV += --conflicts $(OTHER_DEB_DEV_PACKAGE_NAME)
DEB_DEPENDENCIES_THEMISPP = --depends "$(DEB_DEV_PACKAGE_NAME) (= $(VERSION)+$(OS_CODENAME)) | $(OTHER_DEB_DEV_PACKAGE_NAME) (= $(VERSION)+$(OS_CODENAME))"
DEB_DEPENDENCIES_JNI += --depends "$(PACKAGE_NAME) (>= $(VERSION)+$(OS_CODENAME)) | $(OTHER_PACKAGE_NAME) >= ($(VERSION)+$(OS_CODENAME))"
DEB_DEPENDENCIES_DEV += --depends "$(PACKAGE_NAME) = $(VERSION)+$(OS_CODENAME)"
DEB_DEPENDENCIES_THEMISPP = --depends "$(DEB_CANONICAL_DEV_PACKAGE_NAME) = $(VERSION)+$(OS_CODENAME)"
DEB_DEPENDENCIES_JNI += --depends "$(CANONICAL_PACKAGE_NAME) >= $(VERSION)+$(OS_CODENAME)"

ifneq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
RPM_DEPENDENCIES += --depends openssl-libs
endif
RPM_DEPENDENCIES += --conflicts $(OTHER_PACKAGE_NAME)
RPM_DEPENDENCIES_DEV += --depends "$(PACKAGE_NAME) = $(RPM_VERSION)-$(RPM_RELEASE_NUM)"
ifneq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
ifeq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
RPM_DEPENDENCIES += --provides $(CANONICAL_PACKAGE_NAME)
RPM_DEPENDENCIES += --conflicts $(CANONICAL_PACKAGE_NAME)
RPM_DEPENDENCIES += --replaces $(CANONICAL_PACKAGE_NAME)
RPM_DEPENDENCIES_DEV += --provides $(RPM_CANONICAL_DEV_PACKAGE_NAME)
RPM_DEPENDENCIES_DEV += --conflicts $(RPM_CANONICAL_DEV_PACKAGE_NAME)
RPM_DEPENDENCIES_DEV += --replaces $(RPM_CANONICAL_DEV_PACKAGE_NAME)
else
RPM_DEPENDENCIES += --depends openssl-libs
RPM_DEPENDENCIES_DEV += --depends openssl-devel
endif
RPM_DEPENDENCIES_DEV += --conflicts $(OTHER_RPM_DEV_PACKAGE_NAME)
RPM_DEPENDENCIES_THEMISPP = --depends "($(RPM_DEV_PACKAGE_NAME) = $(RPM_VERSION)-$(RPM_RELEASE_NUM) or $(OTHER_RPM_DEV_PACKAGE_NAME) = $(RPM_VERSION)-$(RPM_RELEASE_NUM))"
RPM_DEPENDENCIES_JNI += --depends "($(PACKAGE_NAME) >= $(RPM_VERSION)-$(RPM_RELEASE_NUM) or $(OTHER_PACKAGE_NAME) >= $(RPM_VERSION)-$(RPM_RELEASE_NUM))"
RPM_DEPENDENCIES_DEV += --depends "$(PACKAGE_NAME) = $(RPM_VERSION)-$(RPM_RELEASE_NUM)"
RPM_DEPENDENCIES_THEMISPP = --depends "$(RPM_CANONICAL_DEV_PACKAGE_NAME) = $(RPM_VERSION)-$(RPM_RELEASE_NUM)"
RPM_DEPENDENCIES_JNI += --depends "$(CANONICAL_PACKAGE_NAME) >= $(RPM_VERSION)-$(RPM_RELEASE_NUM)"
RPM_RELEASE_NUM = 1

OS_NAME := $(shell lsb_release -is 2>/dev/null || printf 'unknown')
Expand All @@ -659,26 +674,20 @@ else ifeq ($(OS_NAME),$(filter $(OS_NAME),RedHatEnterpriseServer CentOS))
RPM_LIBDIR := /$(shell [ $$(arch) == "x86_64" ] && echo "lib64" || echo "lib")
endif

CANONICAL_PACKAGE_NAME = libthemis
DEB_CANONICAL_DEV_PACKAGE_NAME = $(CANONICAL_PACKAGE_NAME)-dev
RPM_CANONICAL_DEV_PACKAGE_NAME = $(CANONICAL_PACKAGE_NAME)-devel
ifeq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
PACKAGE_SUFFIX = -boringssl
PACKAGE_NAME = libthemis-boringssl
else
PACKAGE_NAME = libthemis
endif
PACKAGE_NAME = libthemis$(PACKAGE_SUFFIX)
DEB_DEV_PACKAGE_NAME = $(PACKAGE_NAME)-dev
RPM_DEV_PACKAGE_NAME = $(PACKAGE_NAME)-devel
DEB_THEMISPP_PACKAGE_NAME = libthemispp-dev
RPM_THEMISPP_PACKAGE_NAME = libthemispp-devel
JNI_PACKAGE_NAME = libthemis-jni

ifeq ($(PACKAGE_EMBEDDED_BORINGSSL),yes)
OTHER_PACKAGE_NAME = libthemis
OTHER_DEB_DEV_PACKAGE_NAME = libthemis-dev
OTHER_RPM_DEV_PACKAGE_NAME = libthemis-devel
else
OTHER_PACKAGE_NAME = libthemis-boringssl
OTHER_DEB_DEV_PACKAGE_NAME = libthemis-boringssl-dev
OTHER_RPM_DEV_PACKAGE_NAME = libthemis-boringssl-devel
endif

PACKAGE_CATEGORY = security
SHORT_DESCRIPTION = Data security library for network communication and data storage
RPM_SUMMARY = Data security library for network communication and data storage. \
Expand Down Expand Up @@ -918,7 +927,7 @@ ifeq ($(OS_CODENAME),jessie)
else
PHP_DEPENDENCIES += --depends php$(PHP_VERSION_FULL)
endif
PHP_DEPENDENCIES += --depends "$(PACKAGE_NAME) (>= $(VERSION)+$(OS_CODENAME)) | $(OTHER_PACKAGE_NAME) (>= $(VERSION)+$(OS_CODENAME))"
PHP_DEPENDENCIES += --depends "$(CANONICAL_PACKAGE_NAME) >= $(VERSION)+$(OS_CODENAME)"

PHP_PACKAGE_NAME:=libphpthemis-php$(PHP_VERSION_FULL)
PHP_POST_INSTALL_SCRIPT:=./scripts/phpthemis_postinstall.sh
Expand Down

0 comments on commit 960f000

Please sign in to comment.