aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraiuto <aiuto@google.com>2023-01-21 00:42:13 -0500
committerGitHub <noreply@github.com>2023-01-21 00:42:13 -0500
commitd08c88cc9e127f2bef4bcd052de4de25b69183ff (patch)
tree3bfdb176071155c56f53f2b5e52f8c9ff38bff08
parent4926f47c92a2ad6e66387e191e8870bac69ce903 (diff)
parent8ec289604beb093bdb1b9ebc8465c5ec45ee93c0 (diff)
downloadbazelbuild-rules_license-d08c88cc9e127f2bef4bcd052de4de25b69183ff.tar.gz
Merge pull request #69 from aiuto/policy
Bring back the policy checker example
-rw-r--r--examples/policy_checker/BUILD63
-rw-r--r--examples/policy_checker/license_policy.bzl56
-rw-r--r--examples/policy_checker/license_policy_check.bzl94
-rw-r--r--examples/policy_checker/license_policy_provider.bzl24
-rw-r--r--examples/src/BUILD16
-rw-r--r--examples/vendor/acme/BUILD5
-rw-r--r--examples/vendor/libhhgttg/BUILD5
7 files changed, 261 insertions, 2 deletions
diff --git a/examples/policy_checker/BUILD b/examples/policy_checker/BUILD
new file mode 100644
index 0000000..a18bcd2
--- /dev/null
+++ b/examples/policy_checker/BUILD
@@ -0,0 +1,63 @@
+# Example of automated license policy definitions.
+
+load("@rules_license//examples/policy_checker:license_policy.bzl", "license_policy")
+load("@rules_license//examples/policy_checker:license_policy_check.bzl", "license_policy_check")
+
+package(default_package_metadata = ["//:license", "//:package_info"])
+
+# license_policy rules generally appear in a central location per workspace. That
+# should be access controlled by the policy team.
+
+# A production service can use licenses with most conditions
+license_policy(
+ name = "production_service",
+ conditions = [
+ "notice",
+ "restricted_if_statically_linked",
+ ],
+)
+
+# A mobile application usually can not allow end-user replacable libraries.
+# So LGPL code (which is restricted_if_statically_linked) can not be used.
+license_policy(
+ name = "mobile_application",
+ conditions = [
+ "notice",
+ ],
+)
+
+license_policy(
+ name = "special_whitelisted_app",
+ # There could be a whitelist of targets here.
+ conditions = [
+ "notice",
+ "whitelist:acme_corp_paid",
+ ],
+)
+
+# Now we might build checks of critical applications against policies
+#
+# Questions to consider?
+# - Your organization migth want to fold these kinds of checks into
+# wrapper macros around the rules which generate services and apps
+# - You might want to distribute checks to rules alongside the products
+# - Or, you might want to consolidate them in a single place where your
+# compliance team owns them, as this example does
+
+license_policy_check(
+ name = "check_server",
+ policy = ":production_service",
+ target = "//examples/src:my_server",
+)
+
+
+# This is marked manual, so bazel test ... does not fail. Try it yourself with
+# bazel build :check_violating_server
+license_policy_check(
+ name = "check_violating_server",
+ policy = ":production_service",
+ tags = [
+ "manual",
+ ],
+ target = "//examples/src:my_violating_server",
+)
diff --git a/examples/policy_checker/license_policy.bzl b/examples/policy_checker/license_policy.bzl
new file mode 100644
index 0000000..51d6776
--- /dev/null
+++ b/examples/policy_checker/license_policy.bzl
@@ -0,0 +1,56 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+# https://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.
+
+"""license_policy rule.
+
+A license_policy names a set of conditions allowed in the union of all
+license_kinds use by a target. The name of the rule is typically an
+application type (e.g. production_server, mobile_application, ...)
+
+"""
+
+load(
+ "@rules_license//examples/policy_checker:license_policy_provider.bzl",
+ "LicensePolicyInfo"
+)
+
+def _license_policy_impl(ctx):
+ provider = LicensePolicyInfo(
+ name = ctx.attr.name,
+ label = "@%s//%s:%s" % (
+ ctx.label.workspace_name,
+ ctx.label.package,
+ ctx.label.name,
+ ),
+ conditions = ctx.attr.conditions,
+ )
+ return [provider]
+
+_license_policy = rule(
+ implementation = _license_policy_impl,
+ attrs = {
+ "conditions": attr.string_list(
+ doc = "Conditions to be met when using software under this license." +
+ " Conditions are defined by the organization using this license.",
+ mandatory = True,
+ ),
+ },
+)
+
+def license_policy(name, conditions):
+ _license_policy(
+ name = name,
+ conditions = conditions,
+ applicable_licenses = [],
+ )
diff --git a/examples/policy_checker/license_policy_check.bzl b/examples/policy_checker/license_policy_check.bzl
new file mode 100644
index 0000000..2692a01
--- /dev/null
+++ b/examples/policy_checker/license_policy_check.bzl
@@ -0,0 +1,94 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+# https://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.
+
+"""License compliance checking at analysis time."""
+
+load(
+ "@rules_license//examples/policy_checker:license_policy_provider.bzl",
+ "LicensePolicyInfo",
+)
+load(
+ "@rules_license//rules:gather_licenses_info.bzl",
+ "gather_licenses_info",
+)
+load(
+ "@rules_license//rules:providers.bzl",
+ "LicenseInfo",
+ "TransitiveLicensesInfo",
+)
+
+# This is a crude example of the kind of thing which can be done.
+def _license_policy_check_impl(ctx):
+ policy = ctx.attr.policy[LicensePolicyInfo]
+ allowed_conditions = policy.conditions
+ if TransitiveLicensesInfo in ctx.attr.target:
+ for license in ctx.attr.target[TransitiveLicensesInfo].licenses.to_list():
+ for kind in license.license_kinds:
+ # print(kind.conditions)
+ for condition in kind.conditions:
+ if condition not in allowed_conditions:
+ fail("Condition %s violates policy %s" % (
+ condition,
+ policy.label,
+ ))
+
+ if LicenseInfo in ctx.attr.target:
+ for license in ctx.attr.target[LicenseInfo].licenses.to_list():
+ print(license)
+ for kind in license.license_kinds:
+ # print(kind.conditions)
+ for condition in kind.conditions:
+ if condition not in allowed_conditions:
+ fail("Condition %s violates policy %s" % (
+ condition,
+ policy.label,
+ ))
+ return [DefaultInfo()]
+
+_license_policy_check = rule(
+ implementation = _license_policy_check_impl,
+ doc = """Internal implementation method for license_policy_check().""",
+ attrs = {
+ "policy": attr.label(
+ doc = """Policy definition.""",
+ mandatory = True,
+ providers = [LicensePolicyInfo],
+ ),
+ "target": attr.label(
+ doc = """Target to collect LicenseInfo for.""",
+ aspects = [gather_licenses_info],
+ mandatory = True,
+ allow_single_file = True,
+ ),
+ },
+)
+
+def license_policy_check(name, target, policy, **kwargs):
+ """Checks a target against a policy.
+
+ Args:
+ name: The target.
+ target: A target to test for compliance with a policy
+ policy: A rule providing LicensePolicyInfo.
+ **kwargs: other args.
+
+ Usage:
+
+ license_policy_check(
+ name = "license_info",
+ target = ":my_app",
+ policy = "//my_org/compliance/policies:mobile_application",
+ )
+ """
+ _license_policy_check(name = name, target = target, policy = policy, **kwargs)
diff --git a/examples/policy_checker/license_policy_provider.bzl b/examples/policy_checker/license_policy_provider.bzl
new file mode 100644
index 0000000..caecce8
--- /dev/null
+++ b/examples/policy_checker/license_policy_provider.bzl
@@ -0,0 +1,24 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+# https://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.
+
+"""LicensePolicyProvider."""
+
+LicensePolicyInfo = provider(
+ doc = """Declares a policy name and the license conditions allowable under it.""",
+ fields = {
+ "conditions": "List of conditions to be met when using this software.",
+ "label": "The full path to the license policy definition.",
+ "name": "License policy name",
+ },
+)
diff --git a/examples/src/BUILD b/examples/src/BUILD
index ecab5da..0bcb938 100644
--- a/examples/src/BUILD
+++ b/examples/src/BUILD
@@ -16,6 +16,11 @@
load("@rules_license//rules:compliance.bzl", "check_license", "licenses_used")
load("@rules_license//examples/vendor/constant_gen:defs.bzl", "constant_gen")
+package(
+ default_package_metadata = ["//:license", "//:package_info"],
+ default_visibility = ["//visibility:public"],
+)
+
cc_binary(
name = "my_server",
srcs = ["server.cc"],
@@ -59,3 +64,14 @@ py_test(
"@rules_license//tests:license_test_utils",
],
)
+
+# This server uses something under a restricted license
+cc_binary(
+ name = "my_violating_server",
+ srcs = ["server.cc"],
+ deps = [
+ ":message",
+ "@rules_license//examples/vendor/acme",
+ "@rules_license//examples/vendor/libhhgttg",
+ ],
+)
diff --git a/examples/vendor/acme/BUILD b/examples/vendor/acme/BUILD
index 814957d..2e98d98 100644
--- a/examples/vendor/acme/BUILD
+++ b/examples/vendor/acme/BUILD
@@ -15,7 +15,10 @@
load("@rules_license//rules:license.bzl", "license")
-package(default_applicable_licenses = [":license"])
+package(
+ default_applicable_licenses = [":license"],
+ default_visibility = ["//visibility:public"],
+)
# The default license for an entire package is typically named "license".
license(
diff --git a/examples/vendor/libhhgttg/BUILD b/examples/vendor/libhhgttg/BUILD
index 44d2d61..15c7655 100644
--- a/examples/vendor/libhhgttg/BUILD
+++ b/examples/vendor/libhhgttg/BUILD
@@ -18,7 +18,10 @@ load("@rules_license//rules:license.bzl", "license")
# Using a package wide default ensure that all targets are associated with the
# license.
-package(default_applicable_licenses = [":license"])
+package(
+ default_applicable_licenses = [":license"],
+ default_visibility = ["//visibility:public"],
+)
# The default license for an entire package is typically named "license".
license(