Skip to content

Commit

Permalink
Introduce AuthorizationPolicy CRDs
Browse files Browse the repository at this point in the history
Issue #7709 proposes new Custom Resource types to support generalized
authorization policies:

- `AuthorizationPolicy`
- `MeshTLSAuthentication`
- `NetworkAuthentication`

This change introduces these CRDs to the default linkerd installation
(via the `linkerd-crds` chart) and updates the policy controller's
admission webhook to validate these resource types.

This change does NOT update the policy controller to actually honor
these resources when serving policy configuration to proxies.

This change adds policy-controller integration tests to exercise the
admission controller & CRD validation logic. These tests are implemented
in the `policy-test` crate.

Signed-off-by: Oliver Gould <ver@buoyant.io>
  • Loading branch information
olix0r committed Mar 5, 2022
1 parent 9bc61d6 commit 9aac732
Show file tree
Hide file tree
Showing 46 changed files with 4,865 additions and 97 deletions.
132 changes: 127 additions & 5 deletions .github/workflows/policy_controller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- 'deny.toml'
- 'rust-toolchain'
- 'policy-controller/**'
- 'policy-test/**'
- '.github/workflows/policy_controller.yml'

permissions:
Expand All @@ -19,6 +20,8 @@ env:
CARGO_NET_RETRY: 10
RUST_BACKTRACE: short
RUSTUP_MAX_RETRIES: 10
DOCKER_REGISTRY: ghcr.io/linkerd
LINKERD_DOCKER_REGISTRY: ghcr.io/linkerd

jobs:
fmt:
Expand Down Expand Up @@ -58,7 +61,7 @@ jobs:
- run: |
bin/scurl -o /usr/local/bin/cargo-action-fmt "https://github.com/olix0r/cargo-action-fmt/releases/download/release%2F${CARGO_ACTION_FMT_VERSION}/cargo-action-fmt-x86_64-unknown-linux-gnu"
chmod 755 /usr/local/bin/cargo-action-fmt
- run: cargo fetch
- run: cargo fetch --locked
- run: cargo clippy --frozen --all --no-deps --message-format=json | cargo-action-fmt

check:
Expand All @@ -71,7 +74,7 @@ jobs:
- run: |
bin/scurl -o /usr/local/bin/cargo-action-fmt "https://github.com/olix0r/cargo-action-fmt/releases/download/release%2F${CARGO_ACTION_FMT_VERSION}/cargo-action-fmt-x86_64-unknown-linux-gnu"
chmod 755 /usr/local/bin/cargo-action-fmt
- run: cargo fetch
- run: cargo fetch --locked
# Check each crate independently to ensure its Cargo.toml is sufficient.
- run: |
for toml in $(find . -mindepth 2 -name Cargo.toml | sort -r)
Expand All @@ -89,9 +92,9 @@ jobs:
image: docker://rust:1.59.0
steps:
- uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- run: cargo fetch
- run: cargo test --workspace --frozen --no-run
- run: cargo test --workspace --frozen
- run: cargo fetch --locked
- run: cargo test --workspace --exclude=linkerd-policy-test --frozen --no-run
- run: cargo test --workspace --exclude=linkerd-policy-test --frozen

rust-toolchain:
name: rust toolchain
Expand Down Expand Up @@ -120,3 +123,122 @@ jobs:
done
exit $ex
docker_build:
runs-on: ubuntu-20.04
strategy:
matrix:
component:
- controller
- policy-controller
- proxy
name: Docker build (${{ matrix.component }})
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- uses: ./.github/actions/docker-build
with:
docker-registry: ${{ env.DOCKER_REGISTRY }}
docker-target: linux-amd64
component: ${{ matrix.component }}
- name: Create artifact with CLI and image archives
env:
ARCHIVES: /home/runner/archives
run: |
mkdir -p $ARCHIVES
docker save "$DOCKER_REGISTRY/${{ matrix.component }}:$TAG" > $ARCHIVES/${{ matrix.component }}.tar
# `with.path` values do not support environment variables yet, so an
# absolute path is used here.
# https://github.com/actions/upload-artifact/issues/8
- name: Upload artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: image-archives
path: /home/runner/archives

integration_tests:
needs: [docker_build]
name: Policy controller integration tests
runs-on: ubuntu-20.04
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846

- name: Setup path
run: |
mkdir -p $HOME/bin
export PATH="$HOME/bin:$PATH"
echo "PATH=$PATH" >> $GITHUB_ENV
- name: Install kubectl
run: |
bin/scurl -vo $HOME/bin/kubectl "https://dl.k8s.io/release/$(bin/scurl https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
&& chmod 755 $HOME/bin/kubectl
kubectl version --client
- name: Install k3d
run: |
bin/scurl -v https://raw.githubusercontent.com/rancher/k3d/main/install.sh \
| USE_SUDO=false K3D_INSTALL_DIR=$HOME/bin bash
k3d --version
# Go is needed to build the CLI.
- uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab
with:
go-version: '1.17'
- name: Build the Linkerd CLI
run: |
# Compile the linkerd CLI
bin/linkerd version --short --client
- name: Create cluster
run: |
k3d cluster create --no-lb --k3s-arg "--disable=servicelb,traefik@server:0"
kubectl version --short
- name: Download image archives
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741
with:
name: image-archives
path: image-archives
- name: Load images
run: |
docker load <image-archives/controller.tar
docker load <image-archives/policy-controller.tar
docker load <image-archives/proxy.tar
docker pull $DOCKER_REGISTRY/proxy-init:v1.5.3
docker image ls | grep $DOCKER_REGISTRY
tag="$(CI_FORCE_CLEAN=1 bin/root-tag)"
k3d image import \
$DOCKER_REGISTRY/controller:$tag \
$DOCKER_REGISTRY/policy-controller:$tag \
$DOCKER_REGISTRY/proxy:$tag \
$DOCKER_REGISTRY/proxy-init:v1.5.3
- run: bin/linkerd check --pre --wait=1m
- run: bin/linkerd install | kubectl apply -f -
- name: Wait for pods to be ready
run: |
if ! kubectl wait pods -n linkerd -l linkerd.io/control-plane-ns --for condition=Ready --timeout=1m ; then
kubectl describe po -n linkerd >&2
exit 1
fi
- run: bin/linkerd check --wait=1m

- name: Install rust
run: |
rm -rf $HOME/.cargo
bin/scurl -v https://sh.rustup.rs \
| sh -s -- -y --default-toolchain $(cat rust-toolchain)
source $HOME/.cargo/env
echo "PATH=$PATH" >> $GITHUB_ENV
cargo version
- name: Install cargo-action-fmt
run: |
bin/scurl -o /usr/local/bin/cargo-action-fmt "https://github.com/olix0r/cargo-action-fmt/releases/download/release%2F${CARGO_ACTION_FMT_VERSION}/cargo-action-fmt-x86_64-unknown-linux-gnu"
chmod 755 /usr/local/bin/cargo-action-fmt
- run: cargo fetch --locked
- run: cargo test -p linkerd-policy-test --frozen --no-run | cargo-action-fmt
- run: cargo test -p linkerd-policy-test --frozen
32 changes: 30 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ dependencies = [
"memchr",
]

[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]

[[package]]
name = "anyhow"
version = "1.0.55"
Expand Down Expand Up @@ -797,9 +806,9 @@ dependencies = [

[[package]]
name = "kubert"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e81a95b19fad6a076aabe1d5f9b711c4121b2888d418ca1fcca4f8841531ba"
checksum = "b587b7718e2c44d3c045fdd5c3a3515317200b14319439ad41089818078d16e2"
dependencies = [
"clap",
"drain",
Expand Down Expand Up @@ -847,6 +856,7 @@ dependencies = [
"drain",
"futures",
"hyper",
"ipnet",
"jemallocator",
"k8s-openapi",
"kube",
Expand All @@ -856,6 +866,7 @@ dependencies = [
"linkerd-policy-controller-k8s-api",
"linkerd-policy-controller-k8s-index",
"parking_lot 0.12.0",
"serde",
"serde_json",
"thiserror",
"tokio",
Expand Down Expand Up @@ -921,6 +932,22 @@ dependencies = [
"tracing",
]

[[package]]
name = "linkerd-policy-test"
version = "0.1.0"
dependencies = [
"anyhow",
"k8s-openapi",
"kube",
"linkerd-policy-controller-k8s-api",
"rand",
"serde",
"tokio",
"tokio-test",
"tracing",
"tracing-subscriber",
]

[[package]]
name = "linkerd2-proxy-api"
version = "0.3.1"
Expand Down Expand Up @@ -2030,6 +2057,7 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce"
dependencies = [
"ansi_term",
"lazy_static",
"matchers",
"regex",
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[workspace]
resolver = "2"
members = [
"policy-controller",
"policy-controller/core",
"policy-controller/grpc",
"policy-controller/k8s/api",
"policy-controller/k8s/index",
"policy-test",
]

[profile.release]
Expand Down
6 changes: 5 additions & 1 deletion charts/linkerd-control-plane/templates/destination-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,11 @@ webhooks:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["policy.linkerd.io"]
apiVersions: ["v1alpha1", "v1beta1"]
resources: ["servers"]
resources:
- authorizationpolicies
- networkauthentications
- meshtlsauthentications
- servers
sideEffects: None
---
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
101 changes: 101 additions & 0 deletions charts/linkerd-crds/templates/policy/authorizationpolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: authorizationpolicies.policy.linkerd.io
annotations:
{{ include "partials.annotations.created-by" . }}
labels:
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
linkerd.io/control-plane-ns: {{.Release.Namespace}}
spec:
group: policy.linkerd.io
scope: Namespaced
names:
kind: AuthorizationPolicy
plural: authorizationpolicies
singular: authorizationpolicy
shortNames: []
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
required: [spec]
properties:
spec:
description: >-
Authorizes clients to communicate with Linkerd-proxied servers.
type: object
required: [targetRef, requiredAuthenticationRefs]
properties:
targetRef:
description: >-
TODO ...
type: object
# Modified from the gateway API.
# Copyright 2020 The Kubernetes Authors
properties:
group:
description: >-
Group is the group of the referent. When empty, the Kubernetes core API
group is inferred.
maxLength: 253
pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
kind:
description: >-
Kind is the kind of the referent.
maxLength: 63
minLength: 1
pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
type: string
name:
description: Name is the name of the referent.
maxLength: 253
minLength: 1
type: string
required:
- kind
- name
requiredAuthenticationRefs:
description: >-
RequiredAuthenticationRefs enumerates a set of required authentications
type: array
items:
type: object
properties:
group:
description: >-
Group is the group of the referent. When empty, the Kubernetes core API
group is inferred."
maxLength: 253
pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
kind:
description: >-
Kind is the kind of the referent.
maxLength: 63
minLength: 1
pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
type: string
name:
description: >-
Name is the name of the referent. When unspecified, this authentication
refers to all resources of the specified Group and Kind in the specified
namespace.
maxLength: 253
minLength: 1
type: string
namespace:
description: >-
Name is the name of the referent. When unspecified, this authentication
refers to the local namespace.
maxLength: 253
type: string
required:
- kind
- name
Loading

0 comments on commit 9aac732

Please sign in to comment.