# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. """Rules for creating password files and entries.""" load("@bazel_skylib//lib:paths.bzl", "paths") _join_path = paths.join PasswdFileContentProviderInfo = provider( fields = [ "username", "uid", "gid", "info", "home", "create_home", "shell", "name", ], ) def _passwd_entry_impl(ctx): """Creates a passwd_file_content_provider containing a single entry.""" return [PasswdFileContentProviderInfo( username = ctx.attr.username, uid = ctx.attr.uid, gid = ctx.attr.gid, info = ctx.attr.info, home = ctx.attr.home, create_home = ctx.attr.create_home, shell = ctx.attr.shell, name = ctx.attr.name, )] def _passwd_file_impl(ctx): """Core implementation of passwd_file.""" f = "".join(["%s:x:%s:%s:%s:%s:%s\n" % ( entry[PasswdFileContentProviderInfo].username, entry[PasswdFileContentProviderInfo].uid, entry[PasswdFileContentProviderInfo].gid, entry[PasswdFileContentProviderInfo].info, entry[PasswdFileContentProviderInfo].home, entry[PasswdFileContentProviderInfo].shell, ) for entry in ctx.attr.entries]) passwd_file = ctx.actions.declare_file(ctx.label.name) ctx.actions.write(output = passwd_file, content = f) return DefaultInfo(files = depset([passwd_file])) def _format_onwer(t): return ("--owners=%s=%s" % (t[0], t[1])) def _build_homedirs_tar(ctx, passwd_file): homedirs = [] owners_map = {} for entry in ctx.attr.entries: if entry[PasswdFileContentProviderInfo].create_home: homedir = entry[PasswdFileContentProviderInfo].home owners_map[homedir] = "{uid}.{gid}".format( uid = entry[PasswdFileContentProviderInfo].uid, gid = entry[PasswdFileContentProviderInfo].gid, ) homedirs.append(homedir) dest_file = _join_path( ctx.attr.passwd_file_pkg_dir, ctx.label.name, ) args = ctx.actions.args() args.add(ctx.outputs.passwd_tar, format = "--output=%s") args.add("--mode=0o700") args.add(passwd_file, format = "--file=%s=" + dest_file) args.add(dest_file, format = "--modes=%s=" + ctx.attr.passwd_file_mode) args.add_all(homedirs, format_each = "--empty_dir=%s") args.add_all(owners_map.items(), map_each = _format_onwer) ctx.actions.run( executable = ctx.executable.build_tar, inputs = [passwd_file], outputs = [ctx.outputs.passwd_tar], mnemonic = "PasswdTar", arguments = [args], ) def _passwd_tar_impl(ctx): """Core implementation of passwd_tar.""" f = "".join(["%s:x:%s:%s:%s:%s:%s\n" % ( entry[PasswdFileContentProviderInfo].username, entry[PasswdFileContentProviderInfo].uid, entry[PasswdFileContentProviderInfo].gid, entry[PasswdFileContentProviderInfo].info, entry[PasswdFileContentProviderInfo].home, entry[PasswdFileContentProviderInfo].shell, ) for entry in ctx.attr.entries]) passwd_file = ctx.actions.declare_file(ctx.label.name) ctx.actions.write(output = passwd_file, content = f) _build_homedirs_tar(ctx, passwd_file) return DefaultInfo(files = depset([ctx.outputs.passwd_tar])) passwd_entry = rule( attrs = { "create_home": attr.bool(default = True), "gid": attr.int(default = 1000), "home": attr.string(default = "/home"), "info": attr.string(default = "user"), "shell": attr.string(default = "/bin/bash"), "uid": attr.int(default = 1000), "username": attr.string(mandatory = True), }, implementation = _passwd_entry_impl, ) passwd_file = rule( attrs = { "entries": attr.label_list( allow_empty = False, providers = [PasswdFileContentProviderInfo], ), }, executable = False, implementation = _passwd_file_impl, ) passwd_tar = rule( attrs = { "build_tar": attr.label( default = Label("//container:build_tar"), cfg = "exec", executable = True, allow_files = True, ), "entries": attr.label_list( allow_empty = False, providers = [PasswdFileContentProviderInfo], ), "passwd_file_mode": attr.string(default = "0o644"), "passwd_file_pkg_dir": attr.string(mandatory = True), }, executable = False, outputs = { "passwd_tar": "%{name}.tar", }, implementation = _passwd_tar_impl, )