Skip to content

Commit

Permalink
Move the idmapshift binary into privsep.
Browse files Browse the repository at this point in the history
I can't see any evidence that anyone else uses our nova-idmapshift
binary, and it adds a lot of complexity (flags we never call for
example). Move the code we do actually use into the privsep
directory and simplify our calls to it. Remove the extra binary
from our install and documentation.

Change-Id: Ibce28d20d166da154833376cf51f1877b829925e
blueprint: hurrah-for-privsep
  • Loading branch information
mikalstill committed Oct 24, 2017
1 parent a067f8c commit 3f7995f
Show file tree
Hide file tree
Showing 10 changed files with 34 additions and 485 deletions.
1 change: 0 additions & 1 deletion doc/source/cli/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ are documented for completeness and debugging if something goes wrong.
:maxdepth: 1

nova-rootwrap
nova-idmapshift

Deprecated Services
-------------------
Expand Down
92 changes: 0 additions & 92 deletions doc/source/cli/nova-idmapshift.rst

This file was deleted.

1 change: 0 additions & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@
('nova-console', u'Cloud controller fabric'),
('nova-consoleauth', u'Cloud controller fabric'),
('nova-dhcpbridge', u'Cloud controller fabric'),
('nova-idmapshift', u'Cloud controller fabric'),
('nova-manage', u'Cloud controller fabric'),
('nova-network', u'Cloud controller fabric'),
('nova-novncproxy', u'Cloud controller fabric'),
Expand Down
3 changes: 0 additions & 3 deletions etc/nova/rootwrap.d/compute.filters
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,6 @@ brctl: CommandFilter, brctl, root
# nova/virt/xenapi/vm_utils.py: 'mkswap'
mkswap: CommandFilter, mkswap, root

# nova/virt/libvirt/utils.py: 'nova-idmapshift'
nova-idmapshift: CommandFilter, nova-idmapshift, root

# nova/virt/xenapi/vm_utils.py: 'mkfs'
# nova/utils.py: 'mkfs', fs, path, label
mkfs: CommandFilter, mkfs, root
Expand Down
121 changes: 15 additions & 106 deletions nova/cmd/idmapshift.py → nova/privsep/idmapshift.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,56 +11,12 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
##########
IDMapShift
##########
IDMapShift is a tool that properly sets the ownership of a filesystem for use
with linux user namespaces.
=====
Usage
=====
nova-idmapshift -i -u 0:10000:2000 -g 0:10000:2000 path
This command will idempotently shift `path` to proper ownership using
the provided uid and gid mappings.
=========
Arguments
=========
nova-idmapshift -i -c -d -v
-u [[guest-uid:host-uid:count],...]
-g [[guest-gid:host-gid:count],...]
-n [nobody-id]
path
path: Root path of the filesystem to be shifted
-i, --idempotent: Shift operation will only be performed if filesystem
appears unshifted
-c, --confirm: Will perform check on filesystem
Returns 0 when filesystem appears shifted
Returns 1 when filesystem appears unshifted
-d, --dry-run: Print chown operations, but won't perform them
-v, --verbose: Print chown operations while performing them
-u, --uid: User ID mappings, maximum of 3 ranges
-g, --gid: Group ID mappings, maximum of 3 ranges
-n, --nobody: ID to map all unmapped uid and gids to.
=======
Purpose
=======
When using user namespaces with linux containers, the filesystem of the
container must be owned by the targeted user and group ids being applied
to that container. Otherwise, processes inside the container won't be able
Expand All @@ -80,12 +36,13 @@
"""


import argparse
import os
import sys

from nova.i18n import _
from oslo_log import log as logging

import nova.privsep

LOG = logging.getLogger(__name__)
NOBODY_ID = 65534


Expand All @@ -102,30 +59,25 @@ def find_target_id(fsid, mappings, nobody, memo):


def print_chown(path, uid, gid, target_uid, target_gid):
print('%s %s:%s -> %s:%s' % (path, uid, gid, target_uid, target_gid))
LOG.debug('%s %s:%s -> %s:%s', path, uid, gid, target_uid, target_gid)


def shift_path(path, uid_mappings, gid_mappings, nobody, uid_memo, gid_memo,
dry_run=False, verbose=False):
def shift_path(path, uid_mappings, gid_mappings, nobody, uid_memo, gid_memo):
stat = os.lstat(path)
uid = stat.st_uid
gid = stat.st_gid
target_uid = find_target_id(uid, uid_mappings, nobody, uid_memo)
target_gid = find_target_id(gid, gid_mappings, nobody, gid_memo)
if verbose:
print_chown(path, uid, gid, target_uid, target_gid)
if not dry_run:
os.lchown(path, target_uid, target_gid)
print_chown(path, uid, gid, target_uid, target_gid)
os.lchown(path, target_uid, target_gid)


def shift_dir(fsdir, uid_mappings, gid_mappings, nobody,
dry_run=False, verbose=False):
def shift_dir(fsdir, uid_mappings, gid_mappings, nobody):
uid_memo = dict()
gid_memo = dict()

def shift_path_short(p):
shift_path(p, uid_mappings, gid_mappings, nobody,
dry_run=dry_run, verbose=verbose,
uid_memo=uid_memo, gid_memo=gid_memo)

shift_path_short(fsdir)
Expand Down Expand Up @@ -182,51 +134,8 @@ def confirm_dir(fsdir, uid_mappings, gid_mappings, nobody):
return True


def id_map_type(val):
maps = val.split(',')
id_maps = []
for m in maps:
map_vals = m.split(':')

if len(map_vals) != 3:
msg = ('Invalid id map %s, correct syntax is '
'guest-id:host-id:count.')
raise argparse.ArgumentTypeError(msg % val)

try:
vals = [int(i) for i in map_vals]
except ValueError:
msg = 'Invalid id map %s, values must be integers' % val
raise argparse.ArgumentTypeError(msg)

id_maps.append(tuple(vals))
return id_maps


def main():
parser = argparse.ArgumentParser(
description=_('nova-idmapshift is a tool that properly '
'sets the ownership of a filesystem for '
'use with linux user namespaces. '
'This tool can only be used with linux '
'lxc containers. See the man page for '
'details.'))
parser.add_argument('path')
parser.add_argument('-u', '--uid', type=id_map_type, default=[])
parser.add_argument('-g', '--gid', type=id_map_type, default=[])
parser.add_argument('-n', '--nobody', default=NOBODY_ID, type=int)
parser.add_argument('-i', '--idempotent', action='store_true')
parser.add_argument('-c', '--confirm', action='store_true')
parser.add_argument('-d', '--dry-run', action='store_true')
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()

if args.idempotent or args.confirm:
if confirm_dir(args.path, args.uid, args.gid, args.nobody):
sys.exit(0)
else:
if args.confirm:
sys.exit(1)

shift_dir(args.path, args.uid, args.gid, args.nobody,
dry_run=args.dry_run, verbose=args.verbose)
@nova.privsep.sys_admin_pctxt.entrypoint
def shift(path, uid_map, gid_map):
if confirm_dir(uid_map, gid_map, path, NOBODY_ID):
return
shift_dir(path, uid_map, gid_map, NOBODY_ID)
Loading

0 comments on commit 3f7995f

Please sign in to comment.