Skip to content

Commit

Permalink
Remove Gramine dependencies that are not needed at runtime
Browse files Browse the repository at this point in the history
To remove these Gramine dependencies, a new command-line argument
`--remove-gramine-deps` (alias to `-Dremove-gramine-deps=true`) is
introduced. By default it is not set, since removing Gramine
dependencies could also remove packages required by original app.
This option is useful to minimize the final Docker image, in terms of
the amount of installed software.

Signed-off-by: abin <[email protected]>
  • Loading branch information
amathew3 authored and Dmitrii Kuvaiskii committed May 25, 2023
1 parent f2b5cc5 commit 9d3bc47
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Documentation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ of the signing key in them.

Provide passphrase for the enclave signing key (if applicable)

.. option:: -D, --define

Set image sign-time variables during :command:`gsc sign`.

.. option:: --remove-gramine-deps

Remove Gramine dependencies that are not needed at runtime. This may have
a negative side effect of removing even those dependencies that are actually
needed by the original application. Use with care!

.. option:: IMAGE-NAME

Name of the application Docker image
Expand Down
35 changes: 34 additions & 1 deletion gsc.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@
import tomli_w # pylint: disable=import-error
import yaml # pylint: disable=import-error

def test_trueish(value):
if not value:
return False
value = value.casefold()
if value in ('false', 'off', 'no'):
return False
if value in ('true', 'on', 'yes'):
return True
if value.isdigit():
return bool(int(value))
raise ValueError(f'Invalid value for trueish: {value!r}')

def gsc_image_name(original_image_name):
return f'gsc-{original_image_name}'

Expand Down Expand Up @@ -131,6 +143,17 @@ def extract_build_args(args):
sys.exit(1)
return buildargs_dict

def extract_define_args(args):
defineargs_dict = {}
for item in args.define:
if '=' in item:
key, value = item.split('=', maxsplit=1)
defineargs_dict[key] = value
else:
print(f'Invalid value for argument `{item}`, expected `--define {item}=<value>`')
sys.exit(1)
return defineargs_dict

def extract_user_from_image_config(config, env):
user = config['User']
if not user:
Expand Down Expand Up @@ -345,6 +368,9 @@ def gsc_sign_image(args):
# using the user-provided config file with info on OS distro, Gramine version and SGX driver
env = jinja2.Environment()
env.globals.update(yaml.safe_load(args.config_file))
extract_user_from_image_config(unsigned_image.attrs['Config'], env)
env.globals['args'] = extract_define_args(args)
env.tests['trueish'] = test_trueish
distro = env.globals['Distro']

distro, _ = distro.split(':')
Expand Down Expand Up @@ -510,7 +536,14 @@ def gsc_info_image(args):
sub_sign.add_argument('image', help='Name of the application (base) Docker image.')
sub_sign.add_argument('key', help='Key to sign the Intel SGX enclaves inside the Docker image.')
sub_sign.add_argument('-p', '--passphrase', help='Passphrase for the signing key.')

sub_sign.add_argument('-D','--define', action='append', default=[],
help='Set image sign-time variables.')
sub_sign.add_argument('--remove-gramine-deps', action='append_const', dest='define',
const='remove_gramine_deps=true', help='Remove Gramine dependencies that are not needed'
' at runtime.')
sub_sign.add_argument('--no-remove-gramine-deps', action='append_const', dest='define',
const='remove_gramine_deps=false', help='Retain Gramine dependencies that are not needed'
' at runtime.')
sub_info = subcommands.add_parser('info-image', help='Retrieve information about a graminized '
'Docker image')
sub_info.set_defaults(command=gsc_info_image)
Expand Down
10 changes: 10 additions & 0 deletions templates/Dockerfile.common.sign.template
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ FROM {{image}}

COPY --from=unsigned_image /gramine/app_files/*.sig /gramine/app_files/
COPY --from=unsigned_image /gramine/app_files/*.sgx /gramine/app_files/

{% if args.remove_gramine_deps is trueish %}
# Temporarily switch to the root user to uninstall packages
USER root

{% block uninstall %}{% endblock %}

# Switch back to original app_image user
USER {{app_user}}
{% endif %}
16 changes: 16 additions & 0 deletions templates/centos/Dockerfile.sign.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
{% extends "Dockerfile.common.sign.template" %}

{% block uninstall %}
RUN \
pip3 uninstall -y click jinja2 \
tomli tomli-w \
toml \
&& dnf remove -y binutils \
epel-release \
expect \
openssl \
python3-protobuf \
python3-pyelftools \
python3-cryptography \
tcl \
&& dnf -y clean all;
{% endblock %}

{% block path %}export PYTHONPATH="${PYTHONPATH}:$(find /gramine/meson_build_output/lib64 -type d -path '*/site-packages')" &&{% endblock %}
19 changes: 19 additions & 0 deletions templates/debian/Dockerfile.sign.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
{% extends "Dockerfile.common.sign.template" %}

{% block uninstall %}
RUN \
apt-get update -y \
&& apt-get install -y python3-pip \
&& pip3 uninstall -y click jinja2 \
tomli tomli-w \
toml \
&& apt-get remove -y binutils \
expect \
libcurl4-openssl-dev \
openssl \
python3-pip \
python3-protobuf \
python3-cryptography \
python3-pyelftools \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/*;
{% endblock %}

{% block path %}export PYTHONPATH="${PYTHONPATH}:$(find /gramine/meson_build_output/lib -type d -path '*/site-packages')" &&{% endblock %}

0 comments on commit 9d3bc47

Please sign in to comment.