Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for snaps #582

Merged
merged 45 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
db1c941
Set overridable userid's at build time
micahl Sep 27, 2022
2bb294b
make the third-party-notices tool more robust to various cross-buildi…
alexclewontin Oct 24, 2022
fd34fde
Initial snapcrafting for 1.4
alexclewontin Oct 24, 2022
ed36bf9
snapcraft: refine aziotctl interfaces
alexclewontin Oct 29, 2022
8142752
aziotctl: use snapctl for system commands
alexclewontin Nov 3, 2022
36cb299
Add real snap metadata description and summary
alexclewontin Nov 5, 2022
5f964e9
use separate snapctl stop & start calls
alexclewontin Nov 14, 2022
3ac54f5
Replace individual config options with raw config passthrough
alexclewontin Nov 14, 2022
7522429
Use "PLATFORM_FEATURES" instead of "PACKAGE_FORMAT"
alexclewontin Nov 15, 2022
c6f111c
Updates to comment on users.
micahl Nov 18, 2022
6202a67
many: allow build-time setting of the socket directory
alexclewontin Oct 29, 2022
379c320
snapcraft: share sockets & config locations
alexclewontin Nov 30, 2022
70d71d1
Update Makefile
micahl Dec 3, 2022
fcac3fb
Update Makefile
micahl Dec 3, 2022
f6fedd2
Make the snap sockets world writable
alexclewontin Dec 5, 2022
444572d
snap: remove superfluous directory creation from wrapper script
alexclewontin Jan 17, 2023
03d046d
Merge branch 'main' into snapcraft
micahl Jan 27, 2023
bb3e9f2
Skip building TSS libraries.
micahl Jan 31, 2023
8f4ca52
Merge branch 'feature/snapping' of https://github.com/azure/iot-ident…
micahl Feb 13, 2023
7853670
Fix system logs. Bump bindgen/cbindgen
micahl Feb 13, 2023
4a39b00
improve install hook logging
micahl Feb 17, 2023
a748d58
Fixes to unblock publishing to snapcraft
micahl Feb 18, 2023
66fef30
Use env::current_exe instead of cmdline args
micahl Mar 1, 2023
15f2e69
Do not require CAP_FOWNER for aziotctl_common::config::write_file (#520)
alexclewontin Mar 15, 2023
af796f0
snapping: fix hostname reading on Ubuntu Core (#521)
alexclewontin Mar 21, 2023
3db604c
snapping: enable building on arm64 (#522)
alexclewontin Apr 13, 2023
32287b8
Merge remote-tracking branch 'upstream/main' into feature/snapping
damonbarry Sep 5, 2023
65b25c4
snapping: more robust configuration management in a snap (#546)
alexclewontin Sep 9, 2023
3017536
Merge branch 'main' into feature/snapping
damonbarry Nov 21, 2023
4bab49e
Merge branch 'main' into feature/snapping
damonbarry Dec 26, 2023
0ebf7b5
Add snap build to packages workflow (#576)
damonbarry Dec 27, 2023
abc7676
Forward VENDOR_LIBTSS to make in test script
damonbarry Dec 27, 2023
d1958c4
Only include path to vendored tpm2-tss if it was built
damonbarry Dec 29, 2023
0aa863c
Install libtss2-dev for platforms that don't build it
damonbarry Dec 29, 2023
96a579e
Always add target/ to LD_LIBRARY_PATH
damonbarry Dec 29, 2023
347074f
Build snaps with LXD
damonbarry Jan 1, 2024
1754d16
Move snap job to the bottom of the packages workflow
damonbarry Jan 2, 2024
78a6560
Make snap version consistent with other packages
damonbarry Jan 2, 2024
79839ef
Use snapcraft build action
damonbarry Jan 5, 2024
fe56b71
Merge branch 'main' into feature/snapping
damonbarry Jan 8, 2024
e7bfcd6
feature/snapping: bump snap base to core22 (#583)
alexclewontin Jan 18, 2024
06986d4
Build snaps on Ubuntu 22.04 agents
damonbarry Jan 18, 2024
43a110d
Fix agent image name
damonbarry Jan 18, 2024
fc5f3ca
Additional core22 migration (#585)
alexclewontin Jan 24, 2024
f6bc6d5
Merge branch 'main' into feature/snapping
damonbarry Feb 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/packages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,38 @@ jobs:
with:
name: "${{ steps.generate-artifact-properties.outputs.artifact-name }}"
path: 'packages'

snap:
strategy:
fail-fast: false

matrix:
runner:
- arch: amd64
pool: iot-identity-1es-hosted-linux-amd64
image: agent-aziotedge-ubuntu-22.04-msmoby
- arch: aarch64
pool: iot-identity-1es-hosted-linux-arm64
image: agent-aziotedge-ubuntu-22.04-arm64-msmoby

runs-on:
- self-hosted
- 1ES.Pool=${{ matrix.runner.pool }}
- 1ES.ImageOverride=${{ matrix.runner.image }}

steps:
- uses: 'actions/checkout@v3'
with:
submodules: 'recursive'

- name: 'Run'
uses: 'snapcore/action-build@v1'
id: 'snapcraft'
with:
build-info: true

- name: 'Upload'
uses: 'actions/upload-artifact@v3'
with:
name: 'packages_snap_${{ matrix.runner.arch }}'
path: '${{ steps.snapcraft.outputs.snap }}'
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
/packages
/target
.vscode

/parts
/stage
/prime
*.snap
59 changes: 51 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
BINDGEN = bindgen
CBINDGEN = cbindgen

# Default users under which the services will run. Override by specifying on the CLI for make.
USER_AZIOTID ?= aziotid
USER_AZIOTCS ?= aziotcs
USER_AZIOTKS ?= aziotks
USER_AZIOTTPM ?= aziottpm

# Default socket directory. Override by specifying on the CLI for make.
SOCKET_DIR ?= /run/aziot

# 0 => false, _ => true
V = 0

Expand All @@ -20,6 +29,15 @@ ARCH =

INSTALL_PRESET = true

# Enable special features for specific runtime platforms
# '' => none, 'snapd' => snapd features
PLATFORM_FEATURES ?=
CARGO_FEATURES =

ifeq ($(PLATFORM_FEATURES), snapd)
CARGO_FEATURES += --features snapctl
endif

ifeq ($(V), 0)
BINDGEN_VERBOSE =
CARGO_VERBOSE = --quiet
Expand All @@ -38,11 +56,11 @@ else
CARGO_PROFILE_DIRECTORY = release
endif

ifeq ($(ARCH), arm32v7)
ifneq (,$(filter $(ARCH), arm32v7 armhf))
CARGO_TARGET = armv7-unknown-linux-gnueabihf
CROSS_HOST_TRIPLE = arm-linux-gnueabihf
DPKG_ARCH_FLAGS = --host-arch armhf
else ifeq ($(ARCH), aarch64)
else ifneq (,$(filter $(ARCH), aarch64 arm64))
CARGO_TARGET = aarch64-unknown-linux-gnu
CROSS_HOST_TRIPLE = aarch64-linux-gnu
DPKG_ARCH_FLAGS = --host-arch arm64 --host-type aarch64-linux-gnu --target-type aarch64-linux-gnu
Expand All @@ -56,7 +74,12 @@ CARGO_OUTPUT_ABSPATH = $(abspath ./target/$(CARGO_TARGET)/$(CARGO_PROFILE_DIRECT
VENDOR_PREFIX = $(CARGO_OUTPUT_ABSPATH)/fakeroot
VENDOR_PKGCONFIG = $(VENDOR_PREFIX)$(AZIOT_PRIVATE_LIBRARIES)/pkgconfig

CARGO = VENDOR_PREFIX="$(VENDOR_PREFIX)" VENDOR_PKGCONFIG="$(VENDOR_PKGCONFIG)" cargo
CARGO = VENDOR_PREFIX="$(VENDOR_PREFIX)" VENDOR_PKGCONFIG="$(VENDOR_PKGCONFIG)" \
USER_AZIOTID="$(USER_AZIOTID)" \
USER_AZIOTCS="$(USER_AZIOTCS)" \
USER_AZIOTKS="$(USER_AZIOTKS)" \
USER_AZIOTTPM="$(USER_AZIOTTPM)" \
SOCKET_DIR="$(SOCKET_DIR)" cargo

# Some of the targets use bash-isms like `set -o pipefail`
SHELL = /bin/bash
Expand Down Expand Up @@ -96,7 +119,7 @@ default:
# incorrect assumption of /usr/local. There is probably a better
# way to do this...
set -euo pipefail; \
if [ -d third-party/tpm2-tss ]; then \
if [ $(VENDOR_LIBTSS) != 0 -a -d third-party/tpm2-tss ]; then \
cd third-party/tpm2-tss; \
./bootstrap; \
./configure \
Expand All @@ -120,13 +143,13 @@ default:
# See the doc header of the aziot-keys-common crate for more info.
$(CARGO) build \
-p aziot-keys \
$(CARGO_PROFILE) --target $(CARGO_TARGET) $(CARGO_VERBOSE)
$(CARGO_PROFILE) $(CARGO_FEATURES) --target $(CARGO_TARGET) $(CARGO_VERBOSE)

$(CARGO) build \
-p aziotctl \
-p aziotd \
-p aziot-key-openssl-engine-shared \
$(CARGO_PROFILE) --target $(CARGO_TARGET) $(CARGO_VERBOSE)
$(CARGO_PROFILE) $(CARGO_FEATURES) --target $(CARGO_TARGET) $(CARGO_VERBOSE)

clean:
$(CARGO) clean $(CARGO_VERBOSE)
Expand Down Expand Up @@ -309,6 +332,9 @@ deb: dist
# Copy package files
cp -R contrib/debian /tmp/aziot-identity-service-$(PACKAGE_VERSION)/
sed -i -e 's/@version@/$(PACKAGE_VERSION)/g; s/@release@/$(PACKAGE_RELEASE)/g' /tmp/aziot-identity-service-$(PACKAGE_VERSION)/debian/changelog
sed -i -e 's/@user_aziotid@/$(USER_AZIOTID)/g; s/@user_aziotks@/$(USER_AZIOTKS)/g; s/@user_aziotcs@/$(USER_AZIOTCS)/g; s/@user_aziottpm@/$(USER_AZIOTTPM)/g' /tmp/aziot-identity-service-$(PACKAGE_VERSION)/debian/postinst
sed -i -e 's/@user_aziotid@/$(USER_AZIOTID)/g; s/@user_aziotks@/$(USER_AZIOTKS)/g; s/@user_aziotcs@/$(USER_AZIOTCS)/g; s/@user_aziottpm@/$(USER_AZIOTTPM)/g; s|@socket_dir@|$(SOCKET_DIR)|g' /tmp/aziot-identity-service-$(PACKAGE_VERSION)/debian/postrm
sed -i -e 's/@user_aziotid@/$(USER_AZIOTID)/g; s/@user_aziotks@/$(USER_AZIOTKS)/g; s/@user_aziotcs@/$(USER_AZIOTCS)/g; s/@user_aziottpm@/$(USER_AZIOTTPM)/g' /tmp/aziot-identity-service-$(PACKAGE_VERSION)/debian/preinst

cd /tmp/aziot-identity-service-$(PACKAGE_VERSION) && dpkg-buildpackage -us -uc $(DPKG_ARCH_FLAGS)

Expand Down Expand Up @@ -359,6 +385,10 @@ rpm:
-e "s|@devtoolset@|$$DEVTOOLSET|g" \
-e "s|@llvm_toolset@|$$LLVM_TOOLSET|g" \
-e "s|@openssl_engine_filename@|$$OPENSSL_ENGINE_FILENAME|g" \
-e "s/@user_aziotid@/$(USER_AZIOTID)/g" \
-e "s/@user_aziotks@/$(USER_AZIOTKS)/g" \
-e "s/@user_aziotcs@/$(USER_AZIOTCS)/g" \
-e "s/@user_aziottpm@/$(USER_AZIOTTPM)/g" \
>$(RPMBUILDDIR)/SPECS/aziot-identity-service.spec

# Copy preset file to be included in the package
Expand Down Expand Up @@ -427,7 +457,7 @@ install-common:
# tpm2-tss
# See comment above regarding environment bleedover on RPM
# builds.
if [ -d third-party/tpm2-tss ]; then \
if [ $(VENDOR_LIBTSS) != 0 -a -d third-party/tpm2-tss ]; then \
cd third-party/tpm2-tss; \
$(MAKE) libdir=$(AZIOT_PRIVATE_LIBRARIES) install-exec; \
fi
Expand Down Expand Up @@ -457,15 +487,28 @@ install-common:
$(INSTALL) -d -m 0700 $(DESTDIR)$(localstatedir)/lib/aziot/tpmd

# Systemd services and sockets
$(INSTALL) -d $(DESTDIR)$(unitdir)
# NOTE: We do not use "install -D ... -t ..." since it is broken on
# RHEL 7 derivatives and will not be fixed.
# Ref: https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=1758488
for i in cert identity key tpm; do \
OUTPUT_SOCKET="$(DESTDIR)$(unitdir)/aziot-$${i}d.socket"; \
<"$$i/aziot-$${i}d/aziot-$${i}d.socket.in" sed \
-e 's|@user_aziotid@|$(USER_AZIOTID)|' \
-e 's|@user_aziotks@|$(USER_AZIOTKS)|' \
-e 's|@user_aziotcs@|$(USER_AZIOTCS)|' \
-e 's|@user_aziottpm@|$(USER_AZIOTTPM)|' \
-e 's|@socket_dir@|$(SOCKET_DIR)|' \
>"$$OUTPUT_SOCKET"; \
chmod 0644 "$$OUTPUT_SOCKET"; \
OUTPUT_SERVICE="$(DESTDIR)$(unitdir)/aziot-$${i}d.service"; \
$(INSTALL_DATA) -D "$$i/aziot-$${i}d/aziot-$${i}d.socket" "$(DESTDIR)$(unitdir)/aziot-$${i}d.socket"; \
<"$$i/aziot-$${i}d/aziot-$${i}d.service.in" sed \
-e 's|@private-libs@|$(AZIOT_PRIVATE_LIBRARIES)|' \
-e 's|@libexecdir@|$(libexecdir)|' \
-e 's|@user_aziotid@|$(USER_AZIOTID)|' \
-e 's|@user_aziotks@|$(USER_AZIOTKS)|' \
-e 's|@user_aziotcs@|$(USER_AZIOTCS)|' \
-e 's|@user_aziottpm@|$(USER_AZIOTTPM)|' \
>"$$OUTPUT_SERVICE"; \
chmod 0644 "$$OUTPUT_SERVICE"; \
done
Expand Down
6 changes: 6 additions & 0 deletions aziotctl/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[env]
USER_AZIOTID = "aziotid"
USER_AZIOTKS = "aziotks"
USER_AZIOTCS = "aziotcs"
USER_AZIOTTPM = "aziottpm"
SOCKET_DIR = "/run/aziot"
3 changes: 3 additions & 0 deletions aziotctl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ openssl-sys2 = { path = "../openssl-sys2" }

[dev-dependencies]
bytes = "1"

[features]
snapctl = ["aziotctl-common/snapctl"]
3 changes: 3 additions & 0 deletions aziotctl/aziotctl-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ http-common = { path = "../../http-common" }
[dev-dependencies]
bytes = "1"
toml = "0.7"

[features]
snapctl = []
14 changes: 12 additions & 2 deletions aziotctl/aziotctl-common/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,22 @@ pub fn write_file(
let path = path.as_ref();
let path_displayable = path.display();

// We're about to truncate the file anyway, but it is a little safer to
// fully remove it, as a truncating write does not actually reset ownership
// or user permissions (which can lead to needing CAP_FOWNER, as then we
// encounter a set_permissions call on a file we may or may not own). We
// can just ignore any errors returned here as they either mean a) the file
// doesn't exist, in which case great, or b) there is some sort of permission
// or path error which will just crop up in the fs::write call anyway

let _file = fs::remove_file(path);

let () =
fs::write(path, content).with_context(|| format!("could not create {path_displayable}"))?;
let () = unistd::chown(path, Some(user.uid), Some(user.gid))
.with_context(|| format!("could not set ownership on {path_displayable}"))?;
let () = fs::set_permissions(path, fs::Permissions::from_mode(mode))
.with_context(|| format!("could not set permissions on {path_displayable}"))?;
let () = unistd::chown(path, Some(user.uid), Some(user.gid))
.with_context(|| format!("could not set ownership on {path_displayable}"))?;

Ok(())
}
Expand Down
10 changes: 6 additions & 4 deletions aziotctl/aziotctl-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,12 @@ pub fn is_rfc_1035_valid(hostname: &str) -> bool {
}

fn program_name() -> String {
std::env::args_os()
.next()
.and_then(|arg| arg.into_string().ok())
.unwrap_or_else(|| "<current program>".to_owned())
std::env::current_exe()
.expect("Cannot get the exec path")
.file_name()
.and_then(std::ffi::OsStr::to_str)
.unwrap_or("<current program>")
.to_owned()
}

#[cfg(test)]
Expand Down
37 changes: 37 additions & 0 deletions aziotctl/aziotctl-common/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct ServiceDefinition {
}

// Note, the ordering is important, since the first service is considered the root and will be started by the restart command.
#[cfg(not(feature = "snapctl"))]
pub const SERVICE_DEFINITIONS: &[&ServiceDefinition] = &[
&ServiceDefinition {
service: "aziot-identityd.service",
Expand All @@ -37,6 +38,28 @@ pub const SERVICE_DEFINITIONS: &[&ServiceDefinition] = &[
},
];

// Ordering is not important here, we defer it to snapd
#[cfg(feature = "snapctl")]
pub const SERVICE_DEFINITIONS: &[&ServiceDefinition] = &[
&ServiceDefinition {
service: "snap.azure-iot-identity.identityd.service",
sockets: &["aziot-identityd.socket"],
},
&ServiceDefinition {
service: "snap.azure-iot-identity.keyd.service",
sockets: &["aziot-keyd.socket"],
},
&ServiceDefinition {
service: "snap.azure-iot-identity.certd.service",
sockets: &["aziot-certd.socket"],
},
&ServiceDefinition {
service: "snap.azure-iot-identity.tpmd.service",
sockets: &["aziot-tpmd.socket"],
},
];

#[cfg(not(feature = "snapctl"))]
fn print_command_error(result: &std::process::Output) {
use std::io::{self, Write};

Expand All @@ -49,3 +72,17 @@ fn print_command_error(result: &std::process::Output) {
io::stdout().write_all(&result.stderr).unwrap();
eprintln!();
}

#[cfg(feature = "snapctl")]
fn print_command_error(result: &std::process::Output) {
use std::io::{self, Write};

eprintln!("snapctl exited with non-zero status code.");
eprintln!("stdout:");
eprintln!("=======");
io::stdout().write_all(&result.stdout).unwrap();
eprintln!("stderr:");
eprintln!("=======");
io::stdout().write_all(&result.stderr).unwrap();
eprintln!();
}
43 changes: 43 additions & 0 deletions aziotctl/aziotctl-common/src/system/restart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use anyhow::{Context, Result};

use super::{print_command_error, stop, ServiceDefinition};

#[cfg(not(feature = "snapctl"))]
pub fn restart(services: &[&ServiceDefinition]) -> Result<()> {
// stop all services
stop(services)?;
Expand All @@ -20,6 +21,7 @@ pub fn restart(services: &[&ServiceDefinition]) -> Result<()> {
start(services[0].service)
}

#[cfg(not(feature = "snapctl"))]
fn start(name: &str) -> Result<()> {
print!("Starting {name}...");
let result = Command::new("systemctl")
Expand All @@ -35,3 +37,44 @@ fn start(name: &str) -> Result<()> {

Ok(())
}

#[cfg(feature = "snapctl")]
pub fn restart(services: &[&ServiceDefinition]) -> Result<()> {
// stop all services
stop(services)?;

// start all services
start(services)
}

#[cfg(feature = "snapctl")]
pub fn start(services: &[&ServiceDefinition]) -> Result<()> {
let snap_instance_name = match std::env::var("SNAP_INSTANCE_NAME") {
Ok(snap_instance_name) => snap_instance_name,
Err(_) => {
std::env::var("SNAP_NAME").expect("snapctl must be used within the context of a snap")
}
};

print!("Starting {} services...", snap_instance_name);

let service_names = services.iter().map(|s| {
s.service
.trim_start_matches("snap.")
.trim_end_matches(".service")
});

let result = Command::new("snapctl")
.arg("start")
.args(service_names)
.output()
.context("Failed to call snapctl start")?;

if result.status.success() {
println!("Started!");
} else {
print_command_error(&result);
}

Ok(())
}
Loading
Loading