mirror of https://github.com/linkerd/linkerd2.git
Introduce AuthorizationPolicy CRDs (#8007)
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 to handle these resource types. The policy admission controller validates that these resource reference only suppported types. This new functionality is tested at multiple levels: * `linkerd-policy-controller-k8s-index` includes unit tests for the indexer to test how events update the index; * `linkerd-policy-test` includes integration tests that run in-cluster to validate that the gRPC API updates as resources are manipulated; * `linkerd-policy-test` includes integration tests that exercise the admission controller's resource validation; and * `linkerd-policy-test` includes integration tests that ensure that proxies honor authorization resources. This change does NOT update Linkerd's control plane and extensions to use these new authorization primitives. Furthermore, the `linkerd` CLI does not yet support inspecting these new resource types. These enhancements will be made in followup changes. Signed-off-by: Oliver Gould <ver@buoyant.io>
This commit is contained in:
parent
24079ab076
commit
c1a1430d1a
|
@ -958,6 +958,7 @@ dependencies = [
|
|||
"futures",
|
||||
"linkerd-policy-controller-core",
|
||||
"linkerd2-proxy-api",
|
||||
"maplit",
|
||||
"tokio",
|
||||
"tonic",
|
||||
"tracing",
|
||||
|
@ -989,6 +990,7 @@ dependencies = [
|
|||
"kubert",
|
||||
"linkerd-policy-controller-core",
|
||||
"linkerd-policy-controller-k8s-api",
|
||||
"maplit",
|
||||
"parking_lot",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
|
|
|
@ -166,6 +166,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -190,6 +193,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.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: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.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: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
|
@ -61,6 +61,9 @@ Otherwise, you can use the --ignore-cluster flag to overwrite the existing globa
|
|||
|
||||
var (
|
||||
templatesCrdFiles = []string{
|
||||
"templates/policy/authorization-policy.yaml",
|
||||
"templates/policy/meshtls-authentication.yaml",
|
||||
"templates/policy/network-authentication.yaml",
|
||||
"templates/policy/server.yaml",
|
||||
"templates/policy/server-authorization.yaml",
|
||||
"templates/serviceprofile.yaml",
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -161,6 +161,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -185,6 +188,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -161,6 +161,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -185,6 +188,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,4 +1,248 @@
|
|||
---
|
||||
# Source: linkerd-crds/templates/policy/authorization-policy.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
helm.sh/chart: linkerd-crds-
|
||||
linkerd.io/control-plane-ns: linkerd-dev
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
# Source: linkerd-crds/templates/policy/meshtls-authentication.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
helm.sh/chart: linkerd-crds-
|
||||
linkerd.io/control-plane-ns: linkerd-dev
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
# Source: linkerd-crds/templates/policy/network-authentication.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
helm.sh/chart: linkerd-crds-
|
||||
linkerd.io/control-plane-ns: linkerd-dev
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
# Source: linkerd-crds/templates/policy/server.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
|
|
|
@ -1,4 +1,248 @@
|
|||
---
|
||||
# Source: linkerd-crds/templates/policy/authorization-policy.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
helm.sh/chart: linkerd-crds-
|
||||
linkerd.io/control-plane-ns: linkerd-dev
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
# Source: linkerd-crds/templates/policy/meshtls-authentication.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
helm.sh/chart: linkerd-crds-
|
||||
linkerd.io/control-plane-ns: linkerd-dev
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
# Source: linkerd-crds/templates/policy/network-authentication.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/helm linkerd-version
|
||||
labels:
|
||||
helm.sh/chart: linkerd-crds-
|
||||
linkerd.io/control-plane-ns: linkerd-dev
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
# Source: linkerd-crds/templates/policy/server.yaml
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
|
|
|
@ -161,6 +161,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -185,6 +188,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -161,6 +161,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -185,6 +188,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: CliVersion
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: CliVersion
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: CliVersion
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -856,6 +1094,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -880,6 +1121,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -1,6 +1,244 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: authorizationpolicies.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
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 server
|
||||
resources.
|
||||
type: object
|
||||
required: [targetRef, requiredAuthenticationRefs]
|
||||
properties:
|
||||
targetRef:
|
||||
description: >-
|
||||
TargetRef references a resource to which the authorization
|
||||
policy applies.
|
||||
type: object
|
||||
required: [kind, name]
|
||||
# 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
|
||||
requiredAuthenticationRefs:
|
||||
description: >-
|
||||
RequiredAuthenticationRefs enumerates a set of required
|
||||
authentications. ALL authentications must be satisfied for
|
||||
the authorization to apply. If any of the referred objects
|
||||
cannot be found, the authorization will be ignored.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [kind, name]
|
||||
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
|
||||
namespace:
|
||||
description: >-
|
||||
Name is the name of the referent. When unspecified,
|
||||
this authentication refers to the local namespace.
|
||||
maxLength: 253
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: meshtlsauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: MeshTLSAuthentication
|
||||
plural: meshtlsauthentications
|
||||
singular: meshtlsauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
MeshTLSAuthentication defines a list of authenticated client IDs
|
||||
to be referenced by an `AuthorizationPolicy`. If a client
|
||||
connection has the mutually-authenticated identity that matches
|
||||
ANY of the of the provided identities, the connection is
|
||||
considered authenticated.
|
||||
type: object
|
||||
oneOf:
|
||||
- required: [identities]
|
||||
- required: [identityRefs]
|
||||
properties:
|
||||
identities:
|
||||
description: >-
|
||||
Authorizes clients with the provided proxy identity strings
|
||||
(as provided via MTLS)
|
||||
|
||||
The `*` prefix can be used to match all identities in
|
||||
a domain. An identity string of `*` indicates that
|
||||
all authentication clients are authorized.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pattern: '^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||
identityRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
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 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
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: networkauthentications.policy.linkerd.io
|
||||
annotations:
|
||||
linkerd.io/created-by: linkerd/cli dev-undefined
|
||||
labels:
|
||||
helm.sh/chart: linkerd-control-plane-1.1.11-edge
|
||||
linkerd.io/control-plane-ns: linkerd
|
||||
spec:
|
||||
group: policy.linkerd.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: NetworkAuthentication
|
||||
plural: networkauthentications
|
||||
singular: networkauthentication
|
||||
shortNames: []
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
required: [spec]
|
||||
properties:
|
||||
spec:
|
||||
description: >-
|
||||
NetworkAuthentication defines a list of authenticated client
|
||||
networks to be referenced by an `AuthorizationPolicy`. If a
|
||||
client connection originates from ANY of the of the provided
|
||||
networks, the connection is considered authenticated.
|
||||
type: object
|
||||
required: [networks]
|
||||
properties:
|
||||
networks:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [cidr]
|
||||
properties:
|
||||
cidr:
|
||||
description: >-
|
||||
The CIDR of the network to be authorized.
|
||||
type: string
|
||||
except:
|
||||
description: >-
|
||||
A list of IP networks/addresses not to be included in
|
||||
the above `cidr`.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: servers.policy.linkerd.io
|
||||
annotations:
|
||||
|
@ -859,6 +1097,9 @@ webhooks:
|
|||
apiGroups: ["policy.linkerd.io"]
|
||||
apiVersions: ["v1alpha1", "v1beta1"]
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- networkauthentications
|
||||
- meshtlsauthentications
|
||||
- serverauthorizations
|
||||
- servers
|
||||
sideEffects: None
|
||||
|
@ -883,6 +1124,9 @@ rules:
|
|||
- apiGroups:
|
||||
- policy.linkerd.io
|
||||
resources:
|
||||
- authorizationpolicies
|
||||
- meshtlsauthentications
|
||||
- networkauthentications
|
||||
- servers
|
||||
- serverauthorizations
|
||||
verbs:
|
||||
|
|
|
@ -24,9 +24,23 @@ pub type InboundServerStream = Pin<Box<dyn Stream<Item = InboundServer> + Send +
|
|||
/// Inbound server configuration.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct InboundServer {
|
||||
pub name: String,
|
||||
pub reference: ServerRef,
|
||||
|
||||
pub protocol: ProxyProtocol,
|
||||
pub authorizations: HashMap<String, ClientAuthorization>,
|
||||
pub authorizations: HashMap<AuthorizationRef, ClientAuthorization>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ServerRef {
|
||||
Default(String),
|
||||
Server(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum AuthorizationRef {
|
||||
Default(String),
|
||||
ServerAuthorization(String),
|
||||
AuthorizationPolicy(String),
|
||||
}
|
||||
|
||||
/// Describes how a proxy should handle inbound connections.
|
||||
|
@ -63,7 +77,7 @@ pub enum ClientAuthentication {
|
|||
/// Indicates that clients need not be authenticated.
|
||||
Unauthenticated,
|
||||
|
||||
/// Indicates that clients must use TLS bu need not provide a client identity.
|
||||
/// Indicates that clients must use TLS but need not provide a client identity.
|
||||
TlsUnauthenticated,
|
||||
|
||||
/// Indicates that clients must use mutually-authenticated TLS.
|
||||
|
|
|
@ -15,6 +15,7 @@ drain = "0.1"
|
|||
futures = { version = "0.3", default-features = false }
|
||||
linkerd2-proxy-api = { version = "0.3", features = ["inbound", "server"] }
|
||||
linkerd-policy-controller-core = { path = "../core" }
|
||||
maplit = "1"
|
||||
tokio = { version = "1", features = ["macros"] }
|
||||
tonic = { version = "0.6", default-features = false, features = ["transport"] }
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -7,9 +7,11 @@ use linkerd2_proxy_api::inbound::{
|
|||
inbound_server_policies_server::{InboundServerPolicies, InboundServerPoliciesServer},
|
||||
};
|
||||
use linkerd_policy_controller_core::{
|
||||
ClientAuthentication, ClientAuthorization, DiscoverInboundServer, IdentityMatch, InboundServer,
|
||||
InboundServerStream, IpNet, NetworkMatch, ProxyProtocol,
|
||||
AuthorizationRef, ClientAuthentication, ClientAuthorization, DiscoverInboundServer,
|
||||
IdentityMatch, InboundServer, InboundServerStream, IpNet, NetworkMatch, ProxyProtocol,
|
||||
ServerRef,
|
||||
};
|
||||
use maplit::*;
|
||||
use std::sync::Arc;
|
||||
use tracing::trace;
|
||||
|
||||
|
@ -194,9 +196,16 @@ fn to_server(srv: &InboundServer, cluster_networks: &[IpNet]) -> proto::Server {
|
|||
.collect();
|
||||
trace!(?authorizations);
|
||||
|
||||
let labels = vec![("name".to_string(), srv.name.to_string())]
|
||||
.into_iter()
|
||||
.collect();
|
||||
let labels = match &srv.reference {
|
||||
ServerRef::Default(name) => convert_args!(hashmap!(
|
||||
"kind" => "default",
|
||||
"name" => name,
|
||||
)),
|
||||
ServerRef::Server(name) => convert_args!(hashmap!(
|
||||
"kind" => "server",
|
||||
"name" => name,
|
||||
)),
|
||||
};
|
||||
trace!(?labels);
|
||||
|
||||
proto::Server {
|
||||
|
@ -208,7 +217,7 @@ fn to_server(srv: &InboundServer, cluster_networks: &[IpNet]) -> proto::Server {
|
|||
}
|
||||
|
||||
fn to_authz(
|
||||
name: impl ToString,
|
||||
reference: &AuthorizationRef,
|
||||
ClientAuthorization {
|
||||
networks,
|
||||
authentication,
|
||||
|
@ -233,9 +242,20 @@ fn to_authz(
|
|||
.collect()
|
||||
};
|
||||
|
||||
let labels = vec![("name".to_string(), name.to_string())]
|
||||
.into_iter()
|
||||
.collect();
|
||||
let labels = match reference {
|
||||
AuthorizationRef::Default(name) => convert_args!(hashmap!(
|
||||
"kind" => "default",
|
||||
"name" => name,
|
||||
)),
|
||||
AuthorizationRef::ServerAuthorization(name) => convert_args!(hashmap!(
|
||||
"kind" => "serverauthorization",
|
||||
"name" => name,
|
||||
)),
|
||||
AuthorizationRef::AuthorizationPolicy(name) => convert_args!(hashmap!(
|
||||
"kind" => "authorizationpolicy",
|
||||
"name" => name,
|
||||
)),
|
||||
};
|
||||
|
||||
let authn = match authentication {
|
||||
ClientAuthentication::Unauthenticated => proto::Authn {
|
||||
|
|
|
@ -7,7 +7,9 @@ pub mod policy;
|
|||
pub use self::labels::Labels;
|
||||
pub use k8s_openapi::api::{
|
||||
self,
|
||||
core::v1::{Namespace, Node, NodeSpec, Pod, PodSpec, PodStatus},
|
||||
core::v1::{Namespace, Node, NodeSpec, Pod, PodSpec, PodStatus, ServiceAccount},
|
||||
};
|
||||
pub use kube::{
|
||||
api::{ObjectMeta, Resource, ResourceExt},
|
||||
runtime::watcher::Event as WatchEvent,
|
||||
};
|
||||
pub use kube::api::{ObjectMeta, Resource, ResourceExt};
|
||||
pub use kube::runtime::watcher::Event as WatchEvent;
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
pub mod network;
|
||||
pub mod authorization_policy;
|
||||
pub mod meshtls_authentication;
|
||||
mod network;
|
||||
pub mod network_authentication;
|
||||
pub mod server;
|
||||
pub mod server_authorization;
|
||||
pub mod target_ref;
|
||||
|
||||
pub use self::{
|
||||
authorization_policy::{AuthorizationPolicy, AuthorizationPolicySpec},
|
||||
meshtls_authentication::{MeshTLSAuthentication, MeshTLSAuthenticationSpec},
|
||||
network::Network,
|
||||
network_authentication::{NetworkAuthentication, NetworkAuthenticationSpec},
|
||||
server::{Server, ServerSpec},
|
||||
server_authorization::{ServerAuthorization, ServerAuthorizationSpec},
|
||||
target_ref::{ClusterTargetRef, LocalTargetRef, NamespacedTargetRef},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
use super::{LocalTargetRef, NamespacedTargetRef};
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
kube::CustomResource,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
schemars::JsonSchema,
|
||||
)]
|
||||
#[kube(
|
||||
group = "policy.linkerd.io",
|
||||
version = "v1alpha1",
|
||||
kind = "AuthorizationPolicy",
|
||||
namespaced
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AuthorizationPolicySpec {
|
||||
pub target_ref: LocalTargetRef,
|
||||
pub required_authentication_refs: Vec<NamespacedTargetRef>,
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
use super::NamespacedTargetRef;
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
kube::CustomResource,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
schemars::JsonSchema,
|
||||
)]
|
||||
#[kube(
|
||||
group = "policy.linkerd.io",
|
||||
version = "v1alpha1",
|
||||
kind = "MeshTLSAuthentication",
|
||||
namespaced
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MeshTLSAuthenticationSpec {
|
||||
pub identities: Option<Vec<String>>,
|
||||
pub identity_refs: Option<Vec<NamespacedTargetRef>>,
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
pub use super::Network;
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
kube::CustomResource,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
schemars::JsonSchema,
|
||||
)]
|
||||
#[kube(
|
||||
group = "policy.linkerd.io",
|
||||
version = "v1alpha1",
|
||||
kind = "NetworkAuthentication",
|
||||
namespaced
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NetworkAuthenticationSpec {
|
||||
pub networks: Vec<Network>,
|
||||
}
|
|
@ -0,0 +1,351 @@
|
|||
#[derive(
|
||||
Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
|
||||
)]
|
||||
pub struct ClusterTargetRef {
|
||||
pub group: Option<String>,
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
|
||||
)]
|
||||
pub struct LocalTargetRef {
|
||||
pub group: Option<String>,
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
|
||||
)]
|
||||
pub struct NamespacedTargetRef {
|
||||
pub group: Option<String>,
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
pub namespace: Option<String>,
|
||||
}
|
||||
|
||||
impl ClusterTargetRef {
|
||||
pub fn from_resource<T>(resource: &T) -> Self
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
let (group, kind, name) = group_kind_name(resource);
|
||||
Self { group, kind, name }
|
||||
}
|
||||
|
||||
/// Returns the target ref kind, qualified by its group, if necessary.
|
||||
pub fn canonical_kind(&self) -> String {
|
||||
canonical_kind(self.group.as_deref(), &self.kind)
|
||||
}
|
||||
|
||||
/// Checks whether the target references the given resource type
|
||||
pub fn targets_kind<T>(&self) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
targets_kind::<T>(self.group.as_deref(), &self.kind)
|
||||
}
|
||||
|
||||
/// Checks whether the target references the given cluster-level resource
|
||||
pub fn targets<T>(&self, resource: &T) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
if !self.targets_kind::<T>() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if resource.meta().namespace.is_some() {
|
||||
// If the reference or the resource has a namespace, that's a deal-breaker.
|
||||
return false;
|
||||
}
|
||||
|
||||
match resource.meta().name.as_deref() {
|
||||
None => return false,
|
||||
Some(rname) => {
|
||||
if !self.name.eq_ignore_ascii_case(rname) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalTargetRef {
|
||||
pub fn from_resource<T>(resource: &T) -> Self
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
let (group, kind, name) = group_kind_name(resource);
|
||||
Self { group, kind, name }
|
||||
}
|
||||
|
||||
/// Returns the target ref kind, qualified by its group, if necessary.
|
||||
pub fn canonical_kind(&self) -> String {
|
||||
canonical_kind(self.group.as_deref(), &self.kind)
|
||||
}
|
||||
|
||||
/// Checks whether the target references the given resource type
|
||||
pub fn targets_kind<T>(&self) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
targets_kind::<T>(self.group.as_deref(), &self.kind)
|
||||
}
|
||||
|
||||
/// Checks whether the target references the given namespaced resource
|
||||
pub fn targets<T>(&self, resource: &T, local_ns: &str) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
if !self.targets_kind::<T>() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the resource specifies a namespace other than the target or the
|
||||
// default namespace, that's a deal-breaker.
|
||||
match resource.meta().namespace.as_deref() {
|
||||
Some(rns) if rns.eq_ignore_ascii_case(local_ns) => {}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
match resource.meta().name.as_deref() {
|
||||
Some(rname) => rname.eq_ignore_ascii_case(&self.name),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NamespacedTargetRef {
|
||||
pub fn from_resource<T>(resource: &T) -> Self
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
let (group, kind, name) = group_kind_name(resource);
|
||||
let namespace = resource.meta().namespace.clone();
|
||||
Self {
|
||||
group,
|
||||
kind,
|
||||
name,
|
||||
namespace,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the target ref kind, qualified by its group, if necessary.
|
||||
pub fn canonical_kind(&self) -> String {
|
||||
canonical_kind(self.group.as_deref(), &self.kind)
|
||||
}
|
||||
|
||||
/// Checks whether the target references the given resource type
|
||||
pub fn targets_kind<T>(&self) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
targets_kind::<T>(self.group.as_deref(), &self.kind)
|
||||
}
|
||||
|
||||
/// Checks whether the target references the given namespaced resource
|
||||
pub fn targets<T>(&self, resource: &T, local_ns: &str) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
if !self.targets_kind::<T>() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the resource specifies a namespace other than the target or the
|
||||
// default namespace, that's a deal-breaker.
|
||||
let tns = self.namespace.as_deref().unwrap_or(local_ns);
|
||||
match resource.meta().namespace.as_deref() {
|
||||
Some(rns) if rns.eq_ignore_ascii_case(tns) => {}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
match resource.meta().name.as_deref() {
|
||||
None => return false,
|
||||
Some(rname) => {
|
||||
if !self.name.eq_ignore_ascii_case(rname) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn canonical_kind(group: Option<&str>, kind: &str) -> String {
|
||||
if let Some(group) = group {
|
||||
format!("{}.{}", kind, group)
|
||||
} else {
|
||||
kind.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn targets_kind<T>(group: Option<&str>, kind: &str) -> bool
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
let dt = Default::default();
|
||||
|
||||
let mut t_group = &*T::group(&dt);
|
||||
if t_group.is_empty() {
|
||||
t_group = "core";
|
||||
}
|
||||
|
||||
group.unwrap_or("core").eq_ignore_ascii_case(t_group)
|
||||
&& kind.eq_ignore_ascii_case(&*T::kind(&dt))
|
||||
}
|
||||
|
||||
fn group_kind_name<T>(resource: &T) -> (Option<String>, String, String)
|
||||
where
|
||||
T: kube::Resource,
|
||||
T::DynamicType: Default,
|
||||
{
|
||||
let dt = Default::default();
|
||||
|
||||
let group = match T::group(&dt) {
|
||||
g if (*g).is_empty() => None,
|
||||
g => Some(g.to_string()),
|
||||
};
|
||||
|
||||
let kind = T::kind(&dt).to_string();
|
||||
|
||||
let name = resource
|
||||
.meta()
|
||||
.name
|
||||
.clone()
|
||||
.expect("resource must have a name");
|
||||
|
||||
(group, kind, name)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{policy::Server, Namespace, ObjectMeta, ServiceAccount};
|
||||
|
||||
#[test]
|
||||
fn cluster_targets_namespace() {
|
||||
let t = ClusterTargetRef {
|
||||
kind: "Namespace".to_string(),
|
||||
name: "appns".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
assert!(t.targets_kind::<Namespace>());
|
||||
assert!(t.targets(&Namespace {
|
||||
metadata: ObjectMeta {
|
||||
name: Some("appns".to_string()),
|
||||
..ObjectMeta::default()
|
||||
},
|
||||
..Namespace::default()
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn namespaced_targets_service_account() {
|
||||
for tgt in &[
|
||||
NamespacedTargetRef {
|
||||
kind: "ServiceAccount".to_string(),
|
||||
name: "default".to_string(),
|
||||
namespace: Some("appns".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
group: Some("core".to_string()),
|
||||
kind: "ServiceAccount".to_string(),
|
||||
name: "default".to_string(),
|
||||
namespace: Some("appns".to_string()),
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
group: Some("CORE".to_string()),
|
||||
kind: "SERVICEACCOUNT".to_string(),
|
||||
name: "DEFAULT".to_string(),
|
||||
namespace: Some("APPNS".to_string()),
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
kind: "ServiceAccount".to_string(),
|
||||
name: "default".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
] {
|
||||
assert!(tgt.targets_kind::<ServiceAccount>());
|
||||
|
||||
assert!(!tgt.targets_kind::<Namespace>());
|
||||
|
||||
let sa = ServiceAccount {
|
||||
metadata: ObjectMeta {
|
||||
namespace: Some("appns".to_string()),
|
||||
name: Some("default".to_string()),
|
||||
..ObjectMeta::default()
|
||||
},
|
||||
..ServiceAccount::default()
|
||||
};
|
||||
assert!(
|
||||
tgt.targets(&sa, "appns"),
|
||||
"ServiceAccounts are targeted by name: {:#?}",
|
||||
tgt
|
||||
);
|
||||
|
||||
let sa = ServiceAccount {
|
||||
metadata: ObjectMeta {
|
||||
namespace: Some("otherns".to_string()),
|
||||
name: Some("default".to_string()),
|
||||
..ObjectMeta::default()
|
||||
},
|
||||
..ServiceAccount::default()
|
||||
};
|
||||
assert!(
|
||||
!tgt.targets(&sa, "appns"),
|
||||
"ServiceAccounts in other namespaces should not be targeted: {:#?}",
|
||||
tgt
|
||||
);
|
||||
}
|
||||
|
||||
let tgt = NamespacedTargetRef {
|
||||
kind: "ServiceAccount".to_string(),
|
||||
name: "default".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
assert!(
|
||||
{
|
||||
let sa = ServiceAccount {
|
||||
metadata: ObjectMeta {
|
||||
namespace: Some("appns".to_string()),
|
||||
name: Some("special".to_string()),
|
||||
..ObjectMeta::default()
|
||||
},
|
||||
..ServiceAccount::default()
|
||||
};
|
||||
!tgt.targets(&sa, "appns")
|
||||
},
|
||||
"resource comparison uses "
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn namespaced_targets_server() {
|
||||
let tgt = NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "http".to_string(),
|
||||
namespace: Some("appns".to_string()),
|
||||
};
|
||||
|
||||
assert!(tgt.targets_kind::<Server>());
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ tokio = { version = "1", features = ["macros", "rt", "sync"] }
|
|||
tracing = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
maplit = "1"
|
||||
tokio-stream = "0.1"
|
||||
tokio-test = "0.4"
|
||||
tracing-subscriber = "0.3"
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
use anyhow::{bail, Result};
|
||||
use linkerd_policy_controller_k8s_api::{
|
||||
self as k8s,
|
||||
policy::{LocalTargetRef, NamespacedTargetRef},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) struct Spec {
|
||||
pub target: Target,
|
||||
pub authentications: Vec<AuthenticationTarget>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum Target {
|
||||
Server(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) enum AuthenticationTarget {
|
||||
MeshTLS {
|
||||
namespace: Option<String>,
|
||||
name: String,
|
||||
},
|
||||
Network {
|
||||
namespace: Option<String>,
|
||||
name: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl TryFrom<k8s::policy::AuthorizationPolicySpec> for Spec {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(ap: k8s::policy::AuthorizationPolicySpec) -> Result<Self> {
|
||||
let target = target(ap.target_ref)?;
|
||||
|
||||
let authentications = ap
|
||||
.required_authentication_refs
|
||||
.into_iter()
|
||||
.map(authentication_ref)
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
if authentications.is_empty() {
|
||||
bail!("No authentication targets");
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
target,
|
||||
authentications,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub(crate) fn server(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Server(s) => Some(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn target(t: LocalTargetRef) -> Result<Target> {
|
||||
if t.targets_kind::<k8s::policy::Server>() {
|
||||
return Ok(Target::Server(t.name));
|
||||
}
|
||||
|
||||
anyhow::bail!(
|
||||
"unsupported authorization target type: {}",
|
||||
t.canonical_kind()
|
||||
);
|
||||
}
|
||||
|
||||
fn authentication_ref(t: NamespacedTargetRef) -> Result<AuthenticationTarget> {
|
||||
if t.targets_kind::<k8s::policy::MeshTLSAuthentication>() {
|
||||
Ok(AuthenticationTarget::MeshTLS {
|
||||
namespace: t.namespace.map(Into::into),
|
||||
name: t.name,
|
||||
})
|
||||
} else if t.targets_kind::<k8s::policy::NetworkAuthentication>() {
|
||||
Ok(AuthenticationTarget::Network {
|
||||
namespace: t.namespace.map(Into::into),
|
||||
name: t.name,
|
||||
})
|
||||
} else {
|
||||
anyhow::bail!("unsupported authentication target: {}", t.canonical_kind());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -23,8 +23,11 @@
|
|||
#![deny(warnings, rust_2018_idioms)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
mod authorization_policy;
|
||||
mod defaults;
|
||||
mod index;
|
||||
mod meshtls_authentication;
|
||||
mod network_authentication;
|
||||
mod pod;
|
||||
mod server;
|
||||
mod server_authorization;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
use crate::ClusterInfo;
|
||||
use anyhow::Result;
|
||||
use linkerd_policy_controller_core::IdentityMatch;
|
||||
use linkerd_policy_controller_k8s_api::{
|
||||
policy::MeshTLSAuthentication, ResourceExt, ServiceAccount,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) struct Spec {
|
||||
pub matches: Vec<IdentityMatch>,
|
||||
}
|
||||
|
||||
impl Spec {
|
||||
pub(crate) fn try_from_resource(
|
||||
ma: MeshTLSAuthentication,
|
||||
cluster: &ClusterInfo,
|
||||
) -> anyhow::Result<Self> {
|
||||
let namespace = ma
|
||||
.namespace()
|
||||
.expect("MeshTLSAuthentication must have a namespace");
|
||||
|
||||
let identities = ma.spec.identities.into_iter().flatten().map(|s| {
|
||||
Ok(s.parse::<IdentityMatch>()
|
||||
.expect("identity match parsing is infallible"))
|
||||
});
|
||||
|
||||
let identity_refs = ma.spec.identity_refs.into_iter().flatten().map(|tgt| {
|
||||
if tgt.targets_kind::<ServiceAccount>() {
|
||||
let ns = tgt.namespace.as_deref().unwrap_or(&namespace);
|
||||
let id = cluster.service_account_identity(ns, &tgt.name);
|
||||
Ok(IdentityMatch::Exact(id))
|
||||
} else {
|
||||
anyhow::bail!("unsupported target type: {:?}", tgt.canonical_kind())
|
||||
}
|
||||
});
|
||||
|
||||
let matches = identities
|
||||
.chain(identity_refs)
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
if matches.is_empty() {
|
||||
anyhow::bail!("No identities configured");
|
||||
}
|
||||
|
||||
Ok(Spec { matches })
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
use linkerd_policy_controller_core::NetworkMatch;
|
||||
use linkerd_policy_controller_k8s_api::policy::NetworkAuthenticationSpec;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) struct Spec {
|
||||
pub matches: Vec<NetworkMatch>,
|
||||
}
|
||||
|
||||
impl TryFrom<NetworkAuthenticationSpec> for Spec {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(spec: NetworkAuthenticationSpec) -> anyhow::Result<Self> {
|
||||
let matches = spec
|
||||
.networks
|
||||
.into_iter()
|
||||
.map(|n| NetworkMatch {
|
||||
net: n.cidr.into(),
|
||||
except: n.except.into_iter().flatten().map(Into::into).collect(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if matches.is_empty() {
|
||||
anyhow::bail!("No networks configured");
|
||||
}
|
||||
|
||||
Ok(Spec { matches })
|
||||
}
|
||||
}
|
|
@ -1,13 +1,21 @@
|
|||
mod annotation;
|
||||
mod authorization_policy;
|
||||
mod server_authorization;
|
||||
|
||||
use crate::{defaults::DefaultPolicy, index::*, server_authorization::ServerSelector, ClusterInfo};
|
||||
use ahash::AHashMap as HashMap;
|
||||
use kubert::index::IndexNamespacedResource;
|
||||
use linkerd_policy_controller_core::{
|
||||
ClientAuthentication, ClientAuthorization, IdentityMatch, InboundServer, IpNet, Ipv4Net,
|
||||
Ipv6Net, NetworkMatch, ProxyProtocol,
|
||||
AuthorizationRef, ClientAuthentication, ClientAuthorization, IdentityMatch, InboundServer,
|
||||
IpNet, Ipv4Net, Ipv6Net, NetworkMatch, ProxyProtocol, ServerRef,
|
||||
};
|
||||
use linkerd_policy_controller_k8s_api::{
|
||||
self as k8s, api::core::v1::ContainerPort, policy::server::Port, ResourceExt,
|
||||
self as k8s,
|
||||
api::core::v1::ContainerPort,
|
||||
policy::{server::Port, LocalTargetRef, NamespacedTargetRef},
|
||||
ResourceExt,
|
||||
};
|
||||
use maplit::*;
|
||||
use tokio::time;
|
||||
|
||||
#[test]
|
||||
|
@ -19,329 +27,14 @@ fn pod_must_exist_for_lookup() {
|
|||
.expect_err("pod-0.ns-0 must not exist");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn links_named_server_port() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod(
|
||||
"ns-0",
|
||||
"pod-0",
|
||||
Some((
|
||||
"container-0",
|
||||
Some(ContainerPort {
|
||||
name: Some("admin-http".to_string()),
|
||||
container_port: 8080,
|
||||
protocol: Some("TCP".to_string()),
|
||||
..ContainerPort::default()
|
||||
}),
|
||||
)),
|
||||
);
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-admin-http",
|
||||
Port::Name("admin-http".to_string()),
|
||||
None,
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
name: "srv-admin-http".to_string(),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
struct TestConfig {
|
||||
index: SharedIndex,
|
||||
detect_timeout: time::Duration,
|
||||
default_policy: DefaultPolicy,
|
||||
cluster: ClusterInfo,
|
||||
_tracing: tracing::subscriber::DefaultGuard,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn links_unnamed_server_port() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-8080",
|
||||
Port::Number(8080),
|
||||
None,
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
name: "srv-8080".to_string(),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn links_server_authz_by_name() {
|
||||
link_server_authz(ServerSelector::Name("srv-8080".to_string()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn links_server_authz_by_label() {
|
||||
link_server_authz(ServerSelector::Selector(
|
||||
Some(("app", "app-0")).into_iter().collect(),
|
||||
));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn link_server_authz(selector: ServerSelector) {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-8080",
|
||||
Port::Number(8080),
|
||||
Some(("app", "app-0")),
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
name: "srv-8080".to_string(),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
test.index.write().apply(mk_server_authz(
|
||||
"ns-0",
|
||||
"authz-foo",
|
||||
selector,
|
||||
k8s::policy::server_authorization::Client {
|
||||
networks: Some(vec![k8s::policy::server_authorization::Network {
|
||||
cidr: "10.0.0.0/8".parse().unwrap(),
|
||||
except: None,
|
||||
}]),
|
||||
unauthenticated: false,
|
||||
mesh_tls: Some(k8s::policy::server_authorization::MeshTls {
|
||||
identities: Some(vec!["foo.bar".to_string()]),
|
||||
..Default::default()
|
||||
}),
|
||||
},
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(rx.borrow().name, "srv-8080");
|
||||
assert_eq!(rx.borrow().protocol, ProxyProtocol::Http1,);
|
||||
assert!(rx.borrow().authorizations.contains_key("authz-foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_update_deselects_pod() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
test.index.write().reset(
|
||||
vec![mk_pod("ns-0", "pod-0", Some(("container-0", None)))],
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
let mut srv = mk_server(
|
||||
"ns-0",
|
||||
"srv-0",
|
||||
Port::Number(2222),
|
||||
None,
|
||||
None,
|
||||
Some(k8s::policy::server::ProxyProtocol::Http2),
|
||||
);
|
||||
test.index
|
||||
.write()
|
||||
.reset(vec![srv.clone()], Default::default());
|
||||
|
||||
// The default policy applies for all ports.
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
name: "srv-0".into(),
|
||||
protocol: ProxyProtocol::Http2,
|
||||
authorizations: Default::default(),
|
||||
}
|
||||
);
|
||||
|
||||
test.index.write().apply({
|
||||
srv.spec.pod_selector = Some(("label", "value")).into_iter().collect();
|
||||
srv
|
||||
});
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(*rx.borrow(), test.default_server());
|
||||
}
|
||||
|
||||
/// Tests that pod servers are configured with defaults based on the
|
||||
/// workload-defined `DefaultPolicy` policy.
|
||||
///
|
||||
/// Iterates through each default policy and validates that it produces expected
|
||||
/// configurations.
|
||||
#[test]
|
||||
fn default_policy_annotated() {
|
||||
for default in &DEFAULTS {
|
||||
let test = TestConfig::from_default_policy(match *default {
|
||||
// Invert default to ensure override applies.
|
||||
DefaultPolicy::Deny => DefaultPolicy::Allow {
|
||||
authenticated_only: false,
|
||||
cluster_only: false,
|
||||
},
|
||||
_ => DefaultPolicy::Deny,
|
||||
});
|
||||
|
||||
// Initially create the pod without an annotation and check that it gets
|
||||
// the global default.
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
test.index
|
||||
.write()
|
||||
.reset(vec![pod.clone()], Default::default());
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(
|
||||
rx.borrow_and_update().name,
|
||||
format!("default:{}", test.default_policy)
|
||||
);
|
||||
|
||||
// Update the annotation on the pod and check that the watch is updated
|
||||
// with the new default.
|
||||
pod.annotations_mut().insert(
|
||||
"config.linkerd.io/default-inbound-policy".into(),
|
||||
default.to_string(),
|
||||
);
|
||||
test.index.write().apply(pod);
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(rx.borrow().name, format!("default:{}", default));
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests that an invalid workload annotation is ignored in favor of the global
|
||||
/// default.
|
||||
#[tokio::test]
|
||||
async fn default_policy_annotated_invalid() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut p = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
p.annotations_mut().insert(
|
||||
"config.linkerd.io/default-inbound-policy".into(),
|
||||
"bogus".into(),
|
||||
);
|
||||
test.index.write().reset(vec![p], Default::default());
|
||||
|
||||
// Lookup port 2222 -> default config.
|
||||
let rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod must exist in lookups");
|
||||
assert_eq!(*rx.borrow(), test.default_server());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opaque_annotated() {
|
||||
for default in &DEFAULTS {
|
||||
let test = TestConfig::from_default_policy(*default);
|
||||
|
||||
let mut p = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
p.annotations_mut()
|
||||
.insert("config.linkerd.io/opaque-ports".into(), "2222".into());
|
||||
test.index.write().reset(vec![p], Default::default());
|
||||
|
||||
let mut server = test.default_server();
|
||||
server.protocol = ProxyProtocol::Opaque;
|
||||
|
||||
let rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow(), server);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authenticated_annotated() {
|
||||
for default in &DEFAULTS {
|
||||
let test = TestConfig::from_default_policy(*default);
|
||||
|
||||
let mut p = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
p.annotations_mut().insert(
|
||||
"config.linkerd.io/proxy-require-identity-inbound-ports".into(),
|
||||
"2222".into(),
|
||||
);
|
||||
test.index.write().reset(vec![p], Default::default());
|
||||
|
||||
let config = {
|
||||
let policy = match *default {
|
||||
DefaultPolicy::Allow { cluster_only, .. } => DefaultPolicy::Allow {
|
||||
cluster_only,
|
||||
authenticated_only: true,
|
||||
},
|
||||
DefaultPolicy::Deny => DefaultPolicy::Deny,
|
||||
};
|
||||
InboundServer {
|
||||
name: format!("default:{}", policy),
|
||||
authorizations: mk_default_policy(policy, test.cluster.networks),
|
||||
protocol: ProxyProtocol::Detect {
|
||||
timeout: test.detect_timeout,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow(), config);
|
||||
}
|
||||
}
|
||||
|
||||
// === Helpers ===
|
||||
|
||||
const DEFAULTS: [DefaultPolicy; 5] = [
|
||||
DefaultPolicy::Deny,
|
||||
DefaultPolicy::Allow {
|
||||
|
@ -363,21 +56,21 @@ const DEFAULTS: [DefaultPolicy; 5] = [
|
|||
];
|
||||
|
||||
fn mk_pod(
|
||||
ns: impl Into<String>,
|
||||
name: impl Into<String>,
|
||||
containers: impl IntoIterator<Item = (impl Into<String>, impl IntoIterator<Item = ContainerPort>)>,
|
||||
ns: impl ToString,
|
||||
name: impl ToString,
|
||||
containers: impl IntoIterator<Item = (impl ToString, impl IntoIterator<Item = ContainerPort>)>,
|
||||
) -> k8s::Pod {
|
||||
k8s::Pod {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.into()),
|
||||
name: Some(name.into()),
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: Some(k8s::api::core::v1::PodSpec {
|
||||
containers: containers
|
||||
.into_iter()
|
||||
.map(|(name, ports)| k8s::api::core::v1::Container {
|
||||
name: name.into(),
|
||||
name: name.to_string(),
|
||||
ports: Some(ports.into_iter().collect()),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -389,8 +82,8 @@ fn mk_pod(
|
|||
}
|
||||
|
||||
fn mk_server(
|
||||
ns: impl Into<String>,
|
||||
name: impl Into<String>,
|
||||
ns: impl ToString,
|
||||
name: impl ToString,
|
||||
port: Port,
|
||||
srv_labels: impl IntoIterator<Item = (&'static str, &'static str)>,
|
||||
pod_labels: impl IntoIterator<Item = (&'static str, &'static str)>,
|
||||
|
@ -398,8 +91,8 @@ fn mk_server(
|
|||
) -> k8s::policy::Server {
|
||||
k8s::policy::Server {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.into()),
|
||||
name: Some(name.into()),
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
labels: Some(
|
||||
srv_labels
|
||||
.into_iter()
|
||||
|
@ -416,38 +109,10 @@ fn mk_server(
|
|||
}
|
||||
}
|
||||
|
||||
fn mk_server_authz(
|
||||
ns: impl Into<String>,
|
||||
name: impl Into<String>,
|
||||
selector: ServerSelector,
|
||||
client: k8s::policy::server_authorization::Client,
|
||||
) -> k8s::policy::ServerAuthorization {
|
||||
k8s::policy::ServerAuthorization {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.into()),
|
||||
name: Some(name.into()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::ServerAuthorizationSpec {
|
||||
server: match selector {
|
||||
ServerSelector::Name(n) => k8s::policy::server_authorization::Server {
|
||||
name: Some(n),
|
||||
selector: None,
|
||||
},
|
||||
ServerSelector::Selector(s) => k8s::policy::server_authorization::Server {
|
||||
selector: Some(s),
|
||||
name: None,
|
||||
},
|
||||
},
|
||||
client,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_default_policy(
|
||||
da: DefaultPolicy,
|
||||
cluster_nets: Vec<IpNet>,
|
||||
) -> HashMap<String, ClientAuthorization> {
|
||||
) -> HashMap<AuthorizationRef, ClientAuthorization> {
|
||||
let all_nets = vec![Ipv4Net::default().into(), Ipv6Net::default().into()];
|
||||
|
||||
let cluster_nets = cluster_nets.into_iter().map(NetworkMatch::from).collect();
|
||||
|
@ -460,7 +125,7 @@ fn mk_default_policy(
|
|||
authenticated_only: true,
|
||||
cluster_only: false,
|
||||
} => Some((
|
||||
"default:all-authenticated".into(),
|
||||
AuthorizationRef::Default("all-authenticated".to_string()),
|
||||
ClientAuthorization {
|
||||
authentication: authed,
|
||||
networks: all_nets,
|
||||
|
@ -470,7 +135,7 @@ fn mk_default_policy(
|
|||
authenticated_only: false,
|
||||
cluster_only: false,
|
||||
} => Some((
|
||||
"default:all-unauthenticated".into(),
|
||||
AuthorizationRef::Default("all-unauthenticated".to_string()),
|
||||
ClientAuthorization {
|
||||
authentication: ClientAuthentication::Unauthenticated,
|
||||
networks: all_nets,
|
||||
|
@ -480,7 +145,7 @@ fn mk_default_policy(
|
|||
authenticated_only: true,
|
||||
cluster_only: true,
|
||||
} => Some((
|
||||
"default:cluster-authenticated".into(),
|
||||
AuthorizationRef::Default("cluster-authenticated".to_string()),
|
||||
ClientAuthorization {
|
||||
authentication: authed,
|
||||
networks: cluster_nets,
|
||||
|
@ -490,7 +155,7 @@ fn mk_default_policy(
|
|||
authenticated_only: false,
|
||||
cluster_only: true,
|
||||
} => Some((
|
||||
"default:cluster-unauthenticated".into(),
|
||||
AuthorizationRef::Default("cluster-unauthenticated".to_string()),
|
||||
ClientAuthorization {
|
||||
authentication: ClientAuthentication::Unauthenticated,
|
||||
networks: cluster_nets,
|
||||
|
@ -501,14 +166,6 @@ fn mk_default_policy(
|
|||
.collect()
|
||||
}
|
||||
|
||||
struct TestConfig {
|
||||
index: SharedIndex,
|
||||
detect_timeout: time::Duration,
|
||||
default_policy: DefaultPolicy,
|
||||
cluster: ClusterInfo,
|
||||
_tracing: tracing::subscriber::DefaultGuard,
|
||||
}
|
||||
|
||||
impl TestConfig {
|
||||
fn from_default_policy(default_policy: DefaultPolicy) -> Self {
|
||||
let _tracing = Self::init_tracing();
|
||||
|
@ -533,7 +190,7 @@ impl TestConfig {
|
|||
|
||||
fn default_server(&self) -> InboundServer {
|
||||
InboundServer {
|
||||
name: format!("default:{}", self.default_policy),
|
||||
reference: ServerRef::Default(self.default_policy.to_string()),
|
||||
authorizations: mk_default_policy(self.default_policy, self.cluster.networks.clone()),
|
||||
protocol: ProxyProtocol::Detect {
|
||||
timeout: self.detect_timeout,
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
use super::*;
|
||||
|
||||
/// Tests that pod servers are configured with defaults based on the
|
||||
/// workload-defined `DefaultPolicy` policy.
|
||||
///
|
||||
/// Iterates through each default policy and validates that it produces expected
|
||||
/// configurations.
|
||||
#[test]
|
||||
fn default_policy_annotated() {
|
||||
for default in &DEFAULTS {
|
||||
let test = TestConfig::from_default_policy(match *default {
|
||||
// Invert default to ensure override applies.
|
||||
DefaultPolicy::Deny => DefaultPolicy::Allow {
|
||||
authenticated_only: false,
|
||||
cluster_only: false,
|
||||
},
|
||||
_ => DefaultPolicy::Deny,
|
||||
});
|
||||
|
||||
// Initially create the pod without an annotation and check that it gets
|
||||
// the global default.
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
test.index
|
||||
.write()
|
||||
.reset(vec![pod.clone()], Default::default());
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(
|
||||
rx.borrow_and_update().reference,
|
||||
ServerRef::Default(test.default_policy.to_string()),
|
||||
);
|
||||
|
||||
// Update the annotation on the pod and check that the watch is updated
|
||||
// with the new default.
|
||||
pod.annotations_mut().insert(
|
||||
"config.linkerd.io/default-inbound-policy".into(),
|
||||
default.to_string(),
|
||||
);
|
||||
test.index.write().apply(pod);
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
rx.borrow().reference,
|
||||
ServerRef::Default(default.to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests that an invalid workload annotation is ignored in favor of the global
|
||||
/// default.
|
||||
#[tokio::test]
|
||||
async fn default_policy_annotated_invalid() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut p = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
p.annotations_mut().insert(
|
||||
"config.linkerd.io/default-inbound-policy".into(),
|
||||
"bogus".into(),
|
||||
);
|
||||
test.index.write().reset(vec![p], Default::default());
|
||||
|
||||
// Lookup port 2222 -> default config.
|
||||
let rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod must exist in lookups");
|
||||
assert_eq!(*rx.borrow(), test.default_server());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opaque_annotated() {
|
||||
for default in &DEFAULTS {
|
||||
let test = TestConfig::from_default_policy(*default);
|
||||
|
||||
let mut p = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
p.annotations_mut()
|
||||
.insert("config.linkerd.io/opaque-ports".into(), "2222".into());
|
||||
test.index.write().reset(vec![p], Default::default());
|
||||
|
||||
let mut server = test.default_server();
|
||||
server.protocol = ProxyProtocol::Opaque;
|
||||
|
||||
let rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow(), server);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authenticated_annotated() {
|
||||
for default in &DEFAULTS {
|
||||
let test = TestConfig::from_default_policy(*default);
|
||||
|
||||
let mut p = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
p.annotations_mut().insert(
|
||||
"config.linkerd.io/proxy-require-identity-inbound-ports".into(),
|
||||
"2222".into(),
|
||||
);
|
||||
test.index.write().reset(vec![p], Default::default());
|
||||
|
||||
let config = {
|
||||
let policy = match *default {
|
||||
DefaultPolicy::Allow { cluster_only, .. } => DefaultPolicy::Allow {
|
||||
cluster_only,
|
||||
authenticated_only: true,
|
||||
},
|
||||
DefaultPolicy::Deny => DefaultPolicy::Deny,
|
||||
};
|
||||
InboundServer {
|
||||
reference: ServerRef::Default(policy.to_string()),
|
||||
authorizations: mk_default_policy(policy, test.cluster.networks),
|
||||
protocol: ProxyProtocol::Detect {
|
||||
timeout: test.detect_timeout,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow(), config);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn links_authorization_policy_with_mtls_name() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-8080",
|
||||
Port::Number(8080),
|
||||
None,
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
reference: ServerRef::Server("srv-8080".to_string()),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
|
||||
let authz = ClientAuthorization {
|
||||
networks: vec!["10.0.0.0/8".parse::<IpNet>().unwrap().into()],
|
||||
authentication: ClientAuthentication::TlsAuthenticated(vec![IdentityMatch::Exact(
|
||||
"foo.bar".to_string(),
|
||||
)]),
|
||||
};
|
||||
test.index.write().apply(mk_authorization_policy(
|
||||
"ns-0",
|
||||
"authz-foo",
|
||||
"srv-8080",
|
||||
vec![
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "NetworkAuthentication".to_string(),
|
||||
name: "net-foo".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "MeshTLSAuthentication".to_string(),
|
||||
namespace: Some("ns-1".to_string()),
|
||||
name: "mtls-bar".to_string(),
|
||||
},
|
||||
],
|
||||
));
|
||||
test.index.write().apply(mk_network_authentication(
|
||||
"ns-0".to_string(),
|
||||
"net-foo".to_string(),
|
||||
vec![k8s::policy::network_authentication::Network {
|
||||
cidr: "10.0.0.0/8".parse().unwrap(),
|
||||
except: None,
|
||||
}],
|
||||
));
|
||||
test.index.write().apply(mk_meshtls_authentication(
|
||||
"ns-1",
|
||||
"mtls-bar",
|
||||
Some("foo.bar".to_string()),
|
||||
None,
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow(),
|
||||
InboundServer {
|
||||
reference: ServerRef::Server("srv-8080".to_string()),
|
||||
authorizations: hashmap!(
|
||||
AuthorizationRef::AuthorizationPolicy("authz-foo".to_string()) => authz
|
||||
)
|
||||
.into_iter()
|
||||
.collect(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn mk_authorization_policy(
|
||||
ns: impl ToString,
|
||||
name: impl ToString,
|
||||
server: impl ToString,
|
||||
authns: impl IntoIterator<Item = NamespacedTargetRef>,
|
||||
) -> k8s::policy::AuthorizationPolicy {
|
||||
k8s::policy::AuthorizationPolicy {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: server.to_string(),
|
||||
},
|
||||
required_authentication_refs: authns.into_iter().collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_meshtls_authentication(
|
||||
ns: impl ToString,
|
||||
name: impl ToString,
|
||||
identities: impl IntoIterator<Item = String>,
|
||||
refs: impl IntoIterator<Item = NamespacedTargetRef>,
|
||||
) -> k8s::policy::MeshTLSAuthentication {
|
||||
let identities = identities.into_iter().collect::<Vec<_>>();
|
||||
let identity_refs = refs.into_iter().collect::<Vec<_>>();
|
||||
k8s::policy::MeshTLSAuthentication {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::MeshTLSAuthenticationSpec {
|
||||
identities: if identities.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(identities)
|
||||
},
|
||||
identity_refs: if identity_refs.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(identity_refs)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_network_authentication(
|
||||
ns: impl ToString,
|
||||
name: impl ToString,
|
||||
networks: impl IntoIterator<Item = k8s::policy::network_authentication::Network>,
|
||||
) -> k8s::policy::NetworkAuthentication {
|
||||
k8s::policy::NetworkAuthentication {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::NetworkAuthenticationSpec {
|
||||
networks: networks.into_iter().collect(),
|
||||
},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn links_named_server_port() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod(
|
||||
"ns-0",
|
||||
"pod-0",
|
||||
Some((
|
||||
"container-0",
|
||||
Some(ContainerPort {
|
||||
name: Some("admin-http".to_string()),
|
||||
container_port: 8080,
|
||||
protocol: Some("TCP".to_string()),
|
||||
..ContainerPort::default()
|
||||
}),
|
||||
)),
|
||||
);
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-admin-http",
|
||||
Port::Name("admin-http".to_string()),
|
||||
None,
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
reference: ServerRef::Server("srv-admin-http".to_string()),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn links_unnamed_server_port() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-8080",
|
||||
Port::Number(8080),
|
||||
None,
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
reference: ServerRef::Server("srv-8080".to_string()),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_update_deselects_pod() {
|
||||
let test = TestConfig::default();
|
||||
|
||||
test.index.write().reset(
|
||||
vec![mk_pod("ns-0", "pod-0", Some(("container-0", None)))],
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
let mut srv = mk_server(
|
||||
"ns-0",
|
||||
"srv-0",
|
||||
Port::Number(2222),
|
||||
None,
|
||||
None,
|
||||
Some(k8s::policy::server::ProxyProtocol::Http2),
|
||||
);
|
||||
test.index
|
||||
.write()
|
||||
.reset(vec![srv.clone()], Default::default());
|
||||
|
||||
// The default policy applies for all ports.
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 2222)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
reference: ServerRef::Server("srv-0".to_string()),
|
||||
protocol: ProxyProtocol::Http2,
|
||||
authorizations: Default::default(),
|
||||
}
|
||||
);
|
||||
|
||||
test.index.write().apply({
|
||||
srv.spec.pod_selector = Some(("label", "value")).into_iter().collect();
|
||||
srv
|
||||
});
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(*rx.borrow(), test.default_server());
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn links_server_authz_by_name() {
|
||||
link_server_authz(ServerSelector::Name("srv-8080".to_string()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn links_server_authz_by_label() {
|
||||
link_server_authz(ServerSelector::Selector(
|
||||
Some(("app", "app-0")).into_iter().collect(),
|
||||
));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn link_server_authz(selector: ServerSelector) {
|
||||
let test = TestConfig::default();
|
||||
|
||||
let mut pod = mk_pod("ns-0", "pod-0", Some(("container-0", None)));
|
||||
pod.labels_mut()
|
||||
.insert("app".to_string(), "app-0".to_string());
|
||||
test.index.write().apply(pod);
|
||||
|
||||
let mut rx = test
|
||||
.index
|
||||
.write()
|
||||
.pod_server_rx("ns-0", "pod-0", 8080)
|
||||
.expect("pod-0.ns-0 should exist");
|
||||
assert_eq!(*rx.borrow_and_update(), test.default_server());
|
||||
|
||||
test.index.write().apply(mk_server(
|
||||
"ns-0",
|
||||
"srv-8080",
|
||||
Port::Number(8080),
|
||||
Some(("app", "app-0")),
|
||||
Some(("app", "app-0")),
|
||||
Some(k8s::policy::server::ProxyProtocol::Http1),
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
*rx.borrow_and_update(),
|
||||
InboundServer {
|
||||
reference: ServerRef::Server("srv-8080".to_string()),
|
||||
authorizations: Default::default(),
|
||||
protocol: ProxyProtocol::Http1,
|
||||
},
|
||||
);
|
||||
test.index.write().apply(mk_server_authz(
|
||||
"ns-0",
|
||||
"authz-foo",
|
||||
selector,
|
||||
k8s::policy::server_authorization::Client {
|
||||
networks: Some(vec![k8s::policy::server_authorization::Network {
|
||||
cidr: "10.0.0.0/8".parse().unwrap(),
|
||||
except: None,
|
||||
}]),
|
||||
unauthenticated: false,
|
||||
mesh_tls: Some(k8s::policy::server_authorization::MeshTls {
|
||||
identities: Some(vec!["foo.bar".to_string()]),
|
||||
..Default::default()
|
||||
}),
|
||||
},
|
||||
));
|
||||
assert!(rx.has_changed().unwrap());
|
||||
assert_eq!(
|
||||
rx.borrow().reference,
|
||||
ServerRef::Server("srv-8080".to_string())
|
||||
);
|
||||
assert_eq!(rx.borrow().protocol, ProxyProtocol::Http1,);
|
||||
assert!(rx
|
||||
.borrow()
|
||||
.authorizations
|
||||
.contains_key(&AuthorizationRef::ServerAuthorization(
|
||||
"authz-foo".to_string()
|
||||
)));
|
||||
}
|
||||
|
||||
fn mk_server_authz(
|
||||
ns: impl ToString,
|
||||
name: impl ToString,
|
||||
selector: ServerSelector,
|
||||
client: k8s::policy::server_authorization::Client,
|
||||
) -> k8s::policy::ServerAuthorization {
|
||||
k8s::policy::ServerAuthorization {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::ServerAuthorizationSpec {
|
||||
server: match selector {
|
||||
ServerSelector::Name(n) => k8s::policy::server_authorization::Server {
|
||||
name: Some(n),
|
||||
selector: None,
|
||||
},
|
||||
ServerSelector::Selector(s) => k8s::policy::server_authorization::Server {
|
||||
selector: Some(s),
|
||||
name: None,
|
||||
},
|
||||
},
|
||||
client,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,10 +1,15 @@
|
|||
use crate::k8s::{
|
||||
labels,
|
||||
policy::{Server, ServerAuthorization, ServerAuthorizationSpec, ServerSpec},
|
||||
policy::{
|
||||
AuthorizationPolicy, AuthorizationPolicySpec, MeshTLSAuthentication,
|
||||
MeshTLSAuthenticationSpec, NetworkAuthentication, NetworkAuthenticationSpec, Server,
|
||||
ServerAuthorization, ServerAuthorizationSpec, ServerSpec,
|
||||
},
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use futures::future;
|
||||
use hyper::{body::Buf, http, Body, Request, Response};
|
||||
use k8s_openapi::api::core::v1::ServiceAccount;
|
||||
use kube::{core::DynamicObject, Resource, ResourceExt};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::task;
|
||||
|
@ -91,6 +96,18 @@ impl Admission {
|
|||
}
|
||||
|
||||
async fn admit(self, req: AdmissionRequest) -> AdmissionResponse {
|
||||
if is_kind::<AuthorizationPolicy>(&req) {
|
||||
return self.admit_spec::<AuthorizationPolicySpec>(req).await;
|
||||
}
|
||||
|
||||
if is_kind::<MeshTLSAuthentication>(&req) {
|
||||
return self.admit_spec::<MeshTLSAuthenticationSpec>(req).await;
|
||||
}
|
||||
|
||||
if is_kind::<NetworkAuthentication>(&req) {
|
||||
return self.admit_spec::<NetworkAuthenticationSpec>(req).await;
|
||||
}
|
||||
|
||||
if is_kind::<Server>(&req) {
|
||||
return self.admit_spec::<ServerSpec>(req).await;
|
||||
};
|
||||
|
@ -170,6 +187,71 @@ fn parse_spec<T: DeserializeOwned>(req: AdmissionRequest) -> Result<(String, Str
|
|||
Ok((ns, name, spec))
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Validate<AuthorizationPolicySpec> for Admission {
|
||||
async fn validate(self, _ns: &str, _name: &str, spec: AuthorizationPolicySpec) -> Result<()> {
|
||||
// TODO support namespace references?
|
||||
if !spec.target_ref.targets_kind::<Server>() {
|
||||
bail!(
|
||||
"invalid targetRef kind: {}",
|
||||
spec.target_ref.canonical_kind()
|
||||
);
|
||||
}
|
||||
|
||||
let mtls_authns_count = spec
|
||||
.required_authentication_refs
|
||||
.iter()
|
||||
.filter(|authn| authn.targets_kind::<MeshTLSAuthentication>())
|
||||
.count();
|
||||
if mtls_authns_count > 1 {
|
||||
bail!("only a single MeshTLSAuthentication may be set");
|
||||
}
|
||||
|
||||
let net_authns_count = spec
|
||||
.required_authentication_refs
|
||||
.iter()
|
||||
.filter(|authn| authn.targets_kind::<NetworkAuthentication>())
|
||||
.count();
|
||||
if net_authns_count > 1 {
|
||||
bail!("only a single NetworkAuthentication may be set");
|
||||
}
|
||||
|
||||
if mtls_authns_count + net_authns_count < spec.required_authentication_refs.len() {
|
||||
let kinds = spec
|
||||
.required_authentication_refs
|
||||
.iter()
|
||||
.filter(|authn| {
|
||||
!authn.targets_kind::<MeshTLSAuthentication>()
|
||||
&& !authn.targets_kind::<NetworkAuthentication>()
|
||||
})
|
||||
.map(|authn| authn.canonical_kind())
|
||||
.collect::<Vec<_>>();
|
||||
bail!("unsupported authentication kind(s): {}", kinds.join(", "));
|
||||
}
|
||||
|
||||
if mtls_authns_count + net_authns_count == 0 {
|
||||
bail!("at least one authentication reference must be set");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Validate<MeshTLSAuthenticationSpec> for Admission {
|
||||
async fn validate(self, _ns: &str, _name: &str, spec: MeshTLSAuthenticationSpec) -> Result<()> {
|
||||
// The CRD validates identity strings, but does not validate identity references.
|
||||
|
||||
for id in spec.identity_refs.iter().flatten() {
|
||||
if !id.targets_kind::<ServiceAccount>() {
|
||||
bail!("invalid identity target kind: {}", id.canonical_kind());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Validate<ServerSpec> for Admission {
|
||||
/// Checks that `spec` doesn't select the same pod/ports as other existing Servers
|
||||
|
@ -212,6 +294,35 @@ impl Admission {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Validate<NetworkAuthenticationSpec> for Admission {
|
||||
async fn validate(self, _ns: &str, _name: &str, spec: NetworkAuthenticationSpec) -> Result<()> {
|
||||
if spec.networks.is_empty() {
|
||||
bail!("at least one network must be specified");
|
||||
}
|
||||
for net in spec.networks.into_iter() {
|
||||
for except in net.except.into_iter().flatten() {
|
||||
if except.contains(&net.cidr) {
|
||||
bail!(
|
||||
"cidr '{}' is completely negated by exception '{}'",
|
||||
net.cidr,
|
||||
except
|
||||
);
|
||||
}
|
||||
if !net.cidr.contains(&except) {
|
||||
bail!(
|
||||
"cidr '{}' does not include exception '{}'",
|
||||
net.cidr,
|
||||
except
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Validate<ServerAuthorizationSpec> for Admission {
|
||||
async fn validate(self, _ns: &str, _name: &str, spec: ServerAuthorizationSpec) -> Result<()> {
|
||||
|
|
|
@ -125,6 +125,27 @@ async fn main() -> Result<()> {
|
|||
.instrument(info_span!("serverauthorizations")),
|
||||
);
|
||||
|
||||
let authz_policies =
|
||||
runtime.watch_all::<k8s::policy::AuthorizationPolicy>(ListParams::default());
|
||||
tokio::spawn(
|
||||
kubert::index::namespaced(index.clone(), authz_policies)
|
||||
.instrument(info_span!("authorizationpolicies")),
|
||||
);
|
||||
|
||||
let mtls_authns =
|
||||
runtime.watch_all::<k8s::policy::MeshTLSAuthentication>(ListParams::default());
|
||||
tokio::spawn(
|
||||
kubert::index::namespaced(index.clone(), mtls_authns)
|
||||
.instrument(info_span!("meshtlsauthentications")),
|
||||
);
|
||||
|
||||
let network_authns =
|
||||
runtime.watch_all::<k8s::policy::NetworkAuthentication>(ListParams::default());
|
||||
tokio::spawn(
|
||||
kubert::index::namespaced(index.clone(), network_authns)
|
||||
.instrument(info_span!("networkauthentications")),
|
||||
);
|
||||
|
||||
// Run the gRPC server, serving results by looking up against the index handle.
|
||||
tokio::spawn(grpc(
|
||||
grpc_addr,
|
||||
|
|
|
@ -155,7 +155,7 @@ impl Runner {
|
|||
args: Some(
|
||||
vec![
|
||||
"wait",
|
||||
"--timeout=60s",
|
||||
"--timeout=120s",
|
||||
"--for=delete",
|
||||
"--namespace",
|
||||
ns,
|
||||
|
@ -219,13 +219,22 @@ impl Running {
|
|||
&self.name,
|
||||
|obj: Option<&k8s::Pod>| -> bool { obj.and_then(get_exit_code).is_some() },
|
||||
);
|
||||
match time::timeout(time::Duration::from_secs(60), finished).await {
|
||||
match time::timeout(time::Duration::from_secs(120), finished).await {
|
||||
Ok(Ok(())) => {}
|
||||
Ok(Err(error)) => panic!("Failed to wait for exit code: {}: {}", self.name, error),
|
||||
Err(_timeout) => panic!("Timeout waiting for exit code: {}", self.name),
|
||||
};
|
||||
|
||||
let curl_pod = api.get(&self.name).await.expect("pod must exist");
|
||||
get_exit_code(&curl_pod).expect("curl pod must have an exit code")
|
||||
let ex = get_exit_code(&curl_pod).expect("curl pod must have an exit code");
|
||||
|
||||
if let Err(error) = api
|
||||
.delete(&self.name, &kube::api::DeleteParams::background())
|
||||
.await
|
||||
{
|
||||
tracing::trace!(%error, name = %self.name, "Failed to delete pod");
|
||||
}
|
||||
|
||||
ex
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ macro_rules! assert_is_default_all_unauthenticated {
|
|||
($config:expr) => {
|
||||
assert_eq!(
|
||||
$config.labels,
|
||||
Some((
|
||||
"name".to_string(),
|
||||
"default:all-unauthenticated".to_string()
|
||||
))
|
||||
vec![
|
||||
("kind".to_string(), "default".to_string()),
|
||||
("name".to_string(), "all-unauthenticated".to_string()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect()
|
||||
);
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
use linkerd_policy_controller_k8s_api::{
|
||||
self as api,
|
||||
policy::{AuthorizationPolicy, AuthorizationPolicySpec, LocalTargetRef, NamespacedTargetRef},
|
||||
};
|
||||
use linkerd_policy_test::admission;
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_valid() {
|
||||
admission::accepts(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "api".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "MeshTLSAuthentication".to_string(),
|
||||
name: "mtls-clients".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "NetworkAuthentication".to_string(),
|
||||
name: "cluster-nets".to_string(),
|
||||
namespace: Some("linkerd".to_string()),
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_valid_with_only_meshtls() {
|
||||
admission::accepts(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "api".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "MeshTLSAuthentication".to_string(),
|
||||
name: "mtls-clients".to_string(),
|
||||
..Default::default()
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_valid_with_only_network() {
|
||||
admission::accepts(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "api".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "NetworkAuthentication".to_string(),
|
||||
name: "cluster-nets".to_string(),
|
||||
namespace: Some("linkerd".to_string()),
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_empty() {
|
||||
admission::rejects(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec::default(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_empty_required_authentications() {
|
||||
admission::rejects(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "deny".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_target_ref_deployment() {
|
||||
admission::rejects(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("apps".to_string()),
|
||||
kind: "Deployment".to_string(),
|
||||
name: "someapp".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "NetworkAuthentication".to_string(),
|
||||
namespace: Some("linkerd".to_string()),
|
||||
name: "cluster-nets".to_string(),
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_duplicate_mtls_authns() {
|
||||
admission::rejects(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "some-srv".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "MeshTLSAuthentication".to_string(),
|
||||
namespace: Some("some-ns".to_string()),
|
||||
name: "some-ids".to_string(),
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "MeshTLSAuthentication".to_string(),
|
||||
namespace: Some("other-ns".to_string()),
|
||||
name: "other-ids".to_string(),
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_duplicate_network_authns() {
|
||||
admission::rejects(|ns| AuthorizationPolicy {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "Server".to_string(),
|
||||
name: "some-srv".to_string(),
|
||||
},
|
||||
required_authentication_refs: vec![
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "NetworkAuthentication".to_string(),
|
||||
namespace: Some("some-ns".to_string()),
|
||||
name: "some-nets".to_string(),
|
||||
},
|
||||
NamespacedTargetRef {
|
||||
group: Some("policy.linkerd.io".to_string()),
|
||||
kind: "NetworkAuthentication".to_string(),
|
||||
namespace: Some("other-ns".to_string()),
|
||||
name: "other-nets".to_string(),
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
use linkerd_policy_controller_k8s_api::{
|
||||
self as api,
|
||||
policy::{MeshTLSAuthentication, MeshTLSAuthenticationSpec, NamespacedTargetRef},
|
||||
};
|
||||
use linkerd_policy_test::admission;
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_valid_ref() {
|
||||
admission::accepts(|ns| MeshTLSAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: MeshTLSAuthenticationSpec {
|
||||
identity_refs: Some(vec![NamespacedTargetRef {
|
||||
kind: "ServiceAccount".to_string(),
|
||||
name: "default".to_string(),
|
||||
..Default::default()
|
||||
}]),
|
||||
..Default::default()
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_strings() {
|
||||
admission::accepts(|ns| MeshTLSAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: MeshTLSAuthenticationSpec {
|
||||
identities: Some(vec!["example.id".to_string()]),
|
||||
..Default::default()
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_empty() {
|
||||
admission::rejects(|ns| MeshTLSAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: MeshTLSAuthenticationSpec::default(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_both_refs_and_strings() {
|
||||
admission::rejects(|ns| MeshTLSAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: MeshTLSAuthenticationSpec {
|
||||
identities: Some(vec!["example.id".to_string()]),
|
||||
identity_refs: Some(vec![NamespacedTargetRef {
|
||||
kind: "ServiceAccount".to_string(),
|
||||
name: "default".to_string(),
|
||||
..Default::default()
|
||||
}]),
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
use linkerd_policy_controller_k8s_api::{
|
||||
self as api,
|
||||
policy::network_authentication::{Network, NetworkAuthentication, NetworkAuthenticationSpec},
|
||||
};
|
||||
use linkerd_policy_test::admission;
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_valid() {
|
||||
admission::accepts(|ns| NetworkAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: NetworkAuthenticationSpec {
|
||||
networks: vec![
|
||||
Network {
|
||||
cidr: "10.1.0.0/24".parse().unwrap(),
|
||||
except: None,
|
||||
},
|
||||
Network {
|
||||
cidr: "10.1.1.0/24".parse().unwrap(),
|
||||
except: Some(vec!["10.1.1.0/28".parse().unwrap()]),
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn accepts_ip_except() {
|
||||
admission::accepts(|ns| NetworkAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: NetworkAuthenticationSpec {
|
||||
networks: vec![Network {
|
||||
cidr: "10.1.0.0/16".parse().unwrap(),
|
||||
except: Some(vec!["10.1.1.1".parse().unwrap()]),
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_except_whole_cidr() {
|
||||
admission::rejects(|ns| NetworkAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: NetworkAuthenticationSpec {
|
||||
networks: vec![Network {
|
||||
cidr: "10.1.1.0/24".parse().unwrap(),
|
||||
except: Some(vec!["10.1.0.0/16".parse().unwrap()]),
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_except_not_in_cidr() {
|
||||
admission::rejects(|ns| NetworkAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: NetworkAuthenticationSpec {
|
||||
networks: vec![Network {
|
||||
cidr: "10.1.1.0/24".parse().unwrap(),
|
||||
except: Some(vec!["10.1.2.0/24".parse().unwrap()]),
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_invalid_cidr() {
|
||||
// Duplicate the CRD with relaxed validation so we can send an invalid CIDR value.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
kube::CustomResource,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
schemars::JsonSchema,
|
||||
)]
|
||||
#[kube(
|
||||
group = "policy.linkerd.io",
|
||||
version = "v1alpha1",
|
||||
kind = "NetworkAuthentication",
|
||||
namespaced
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NetworkAuthenticationSpec {
|
||||
pub networks: Vec<Network>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Network {
|
||||
pub cidr: String,
|
||||
pub except: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
admission::rejects(|ns| NetworkAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: NetworkAuthenticationSpec {
|
||||
networks: vec![Network {
|
||||
cidr: "10.1.0.0/16".to_string(),
|
||||
except: Some(vec!["bogus".to_string()]),
|
||||
}],
|
||||
},
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn rejects_empty() {
|
||||
admission::rejects(|ns| NetworkAuthentication {
|
||||
metadata: api::ObjectMeta {
|
||||
namespace: Some(ns),
|
||||
name: Some("test".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: NetworkAuthenticationSpec { networks: vec![] },
|
||||
})
|
||||
.await;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
use futures::prelude::*;
|
||||
use kube::ResourceExt;
|
||||
use linkerd_policy_controller_core::{Ipv4Net, Ipv6Net};
|
||||
use linkerd_policy_controller_k8s_api as k8s;
|
||||
use linkerd_policy_test::{
|
||||
assert_is_default_all_unauthenticated, assert_protocol_detect, create, create_ready_pod, grpc,
|
||||
|
@ -55,7 +56,7 @@ async fn server_with_server_authorization() {
|
|||
assert_eq!(config.authorizations, vec![]);
|
||||
assert_eq!(
|
||||
config.labels,
|
||||
convert_args!(hashmap!("name" => "linkerd-admin")),
|
||||
convert_args!(hashmap!("kind" => "server", "name" => "linkerd-admin")),
|
||||
);
|
||||
|
||||
// Create a server authorizaation that refers to the `linkerd-admin`
|
||||
|
@ -99,6 +100,7 @@ async fn server_with_server_authorization() {
|
|||
assert_eq!(
|
||||
config.authorizations.first().unwrap().labels,
|
||||
convert_args!(hashmap!(
|
||||
"kind" => "serverauthorization",
|
||||
"name" => "all-admin",
|
||||
)),
|
||||
);
|
||||
|
@ -118,7 +120,7 @@ async fn server_with_server_authorization() {
|
|||
);
|
||||
assert_eq!(
|
||||
config.labels,
|
||||
convert_args!(hashmap!("name" => server.name()))
|
||||
convert_args!(hashmap!("kind" => "server", "name" => server.name()))
|
||||
);
|
||||
|
||||
// Delete the `Server` and ensure that the update reverts to the
|
||||
|
@ -139,6 +141,142 @@ async fn server_with_server_authorization() {
|
|||
.await;
|
||||
}
|
||||
|
||||
/// Creates a pod, watches its policy, and updates policy resources that impact
|
||||
/// the watch.
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn server_with_authorization_policy() {
|
||||
with_temp_ns(|client, ns| async move {
|
||||
// Create a pod that does nothing. It's injected with a proxy, so we can
|
||||
// attach policies to its admin server.
|
||||
let pod = create_ready_pod(&client, mk_pause(&ns, "pause")).await;
|
||||
tracing::trace!(?pod);
|
||||
|
||||
// Port-forward to the control plane and start watching the pod's admin
|
||||
// server's policy and ensure that the first update uses the default
|
||||
// policy.
|
||||
let mut policy_api = grpc::PolicyClient::port_forwarded(&client).await;
|
||||
let mut rx = policy_api
|
||||
.watch_port(&ns, &pod.name(), 4191)
|
||||
.await
|
||||
.expect("failed to establish watch");
|
||||
let config = rx
|
||||
.next()
|
||||
.await
|
||||
.expect("watch must not fail")
|
||||
.expect("watch must return an initial config");
|
||||
tracing::trace!(?config);
|
||||
assert_is_default_all_unauthenticated!(config);
|
||||
assert_protocol_detect!(config);
|
||||
|
||||
// Create a server that selects the pod's proxy admin server and ensure
|
||||
// that the update now uses this server, which has no authorizations
|
||||
let server = create(&client, mk_admin_server(&ns, "linkerd-admin")).await;
|
||||
let config = rx
|
||||
.next()
|
||||
.await
|
||||
.expect("watch must not fail")
|
||||
.expect("watch must return an updated config");
|
||||
tracing::trace!(?config);
|
||||
assert_eq!(
|
||||
config.protocol,
|
||||
Some(grpc::inbound::ProxyProtocol {
|
||||
kind: Some(grpc::inbound::proxy_protocol::Kind::Http1(
|
||||
grpc::inbound::proxy_protocol::Http1::default()
|
||||
)),
|
||||
}),
|
||||
);
|
||||
assert_eq!(config.authorizations, vec![]);
|
||||
assert_eq!(
|
||||
config.labels,
|
||||
convert_args!(hashmap!("kind" => "server", "name" => server.name()))
|
||||
);
|
||||
|
||||
let all_nets = create(
|
||||
&client,
|
||||
k8s::policy::NetworkAuthentication {
|
||||
metadata: kube::api::ObjectMeta {
|
||||
namespace: Some(ns.clone()),
|
||||
name: Some("all-admin".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::NetworkAuthenticationSpec {
|
||||
networks: vec![
|
||||
k8s::policy::network_authentication::Network {
|
||||
cidr: Ipv4Net::default().into(),
|
||||
except: None,
|
||||
},
|
||||
k8s::policy::network_authentication::Network {
|
||||
cidr: Ipv6Net::default().into(),
|
||||
except: None,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let authz_policy = create(
|
||||
&client,
|
||||
k8s::policy::AuthorizationPolicy {
|
||||
metadata: kube::api::ObjectMeta {
|
||||
namespace: Some(ns.clone()),
|
||||
name: Some("all-admin".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::AuthorizationPolicySpec {
|
||||
target_ref: k8s::policy::LocalTargetRef::from_resource(&server),
|
||||
required_authentication_refs: vec![
|
||||
k8s::policy::NamespacedTargetRef::from_resource(&all_nets),
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let config = time::timeout(time::Duration::from_secs(10), rx.next())
|
||||
.await
|
||||
.expect("watch must update within 10s")
|
||||
.expect("watch must not fail")
|
||||
.expect("watch must return an updated config");
|
||||
tracing::trace!(?config);
|
||||
assert_eq!(
|
||||
config.protocol,
|
||||
Some(grpc::inbound::ProxyProtocol {
|
||||
kind: Some(grpc::inbound::proxy_protocol::Kind::Http1(
|
||||
grpc::inbound::proxy_protocol::Http1::default()
|
||||
)),
|
||||
}),
|
||||
);
|
||||
assert_eq!(config.authorizations.len(), 1);
|
||||
assert_eq!(
|
||||
config.authorizations.first().unwrap().labels,
|
||||
convert_args!(hashmap!(
|
||||
"kind" => "authorizationpolicy",
|
||||
"name" => authz_policy.name(),
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
*config
|
||||
.authorizations
|
||||
.first()
|
||||
.unwrap()
|
||||
.authentication
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
grpc::inbound::Authn {
|
||||
permit: Some(grpc::inbound::authn::Permit::Unauthenticated(
|
||||
grpc::inbound::authn::PermitUnauthenticated {}
|
||||
)),
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
config.labels,
|
||||
convert_args!(hashmap!("kind" => "server", "name" => server.name()))
|
||||
);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
fn mk_pause(ns: &str, name: &str) -> k8s::Pod {
|
||||
k8s::Pod {
|
||||
metadata: k8s::ObjectMeta {
|
||||
|
|
|
@ -0,0 +1,375 @@
|
|||
use linkerd_policy_controller_k8s_api::{
|
||||
self as k8s,
|
||||
policy::{LocalTargetRef, NamespacedTargetRef},
|
||||
};
|
||||
use linkerd_policy_test::{create, create_ready_pod, curl, nginx, with_temp_ns, LinkerdInject};
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn meshtls() {
|
||||
with_temp_ns(|client, ns| async move {
|
||||
// First create all of the policies we'll need so that the nginx pod
|
||||
// starts up with the correct policy (to prevent races).
|
||||
//
|
||||
// The policy requires that all connections are authenticated with MeshTLS.
|
||||
let (srv, all_mtls) = tokio::join!(
|
||||
create(&client, nginx::server(&ns)),
|
||||
create(&client, all_authenticated(&ns))
|
||||
);
|
||||
create(
|
||||
&client,
|
||||
authz_policy(
|
||||
&ns,
|
||||
"nginx",
|
||||
&srv,
|
||||
Some(NamespacedTargetRef::from_resource(&all_mtls)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Create the nginx pod and wait for it to be ready.
|
||||
tokio::join!(
|
||||
create(&client, nginx::service(&ns)),
|
||||
create_ready_pod(&client, nginx::pod(&ns))
|
||||
);
|
||||
|
||||
let curl = curl::Runner::init(&client, &ns).await;
|
||||
let (injected, uninjected) = tokio::join!(
|
||||
curl.run("curl-injected", "http://nginx", LinkerdInject::Enabled),
|
||||
curl.run("curl-uninjected", "http://nginx", LinkerdInject::Disabled),
|
||||
);
|
||||
let (injected_status, uninjected_status) =
|
||||
tokio::join!(injected.exit_code(), uninjected.exit_code());
|
||||
assert_eq!(
|
||||
injected_status, 0,
|
||||
"uninjected curl must fail to contact nginx"
|
||||
);
|
||||
assert_ne!(uninjected_status, 0, "injected curl must contact nginx");
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn network() {
|
||||
// In order to test the network policy, we need to create the client pod
|
||||
// before creating the authorization policy. To avoid races, we do this by
|
||||
// creating a `curl-lock` configmap that prevents curl from actually being
|
||||
// executed. Once nginx is running with the correct policy, the configmap is
|
||||
// deleted to unblock the curl pods.
|
||||
with_temp_ns(|client, ns| async move {
|
||||
let curl = curl::Runner::init(&client, &ns).await;
|
||||
curl.create_lock().await;
|
||||
|
||||
// Create a curl pod and wait for it to get an IP.
|
||||
let blessed = curl
|
||||
.run("curl-blessed", "http://nginx", LinkerdInject::Disabled)
|
||||
.await;
|
||||
let blessed_ip = blessed.ip().await;
|
||||
tracing::debug!(curl.blessed.ip = %blessed_ip);
|
||||
|
||||
// Once we know the IP of the (blocked) pod, create an nginx
|
||||
// authorization policy that permits connections from this pod.
|
||||
let (srv, allow_ips) = tokio::join!(
|
||||
create(&client, nginx::server(&ns)),
|
||||
create(&client, allow_ips(&ns, Some(blessed_ip)))
|
||||
);
|
||||
create(
|
||||
&client,
|
||||
authz_policy(
|
||||
&ns,
|
||||
"nginx",
|
||||
&srv,
|
||||
Some(NamespacedTargetRef::from_resource(&allow_ips)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Start nginx with the policy.
|
||||
tokio::join!(
|
||||
create(&client, nginx::service(&ns)),
|
||||
create_ready_pod(&client, nginx::pod(&ns))
|
||||
);
|
||||
|
||||
// Once the nginx pod is ready, delete the `curl-lock` configmap to
|
||||
// unblock curl from running.
|
||||
curl.delete_lock().await;
|
||||
|
||||
// The blessed pod should be able to connect to the nginx pod.
|
||||
let status = blessed.exit_code().await;
|
||||
assert_eq!(status, 0, "blessed curl pod must succeed");
|
||||
|
||||
// Create another curl pod that is not included in the authorization. It
|
||||
// should fail to connect to the nginx pod.
|
||||
let status = curl
|
||||
.run("curl-cursed", "http://nginx", LinkerdInject::Disabled)
|
||||
.await
|
||||
.exit_code()
|
||||
.await;
|
||||
assert_ne!(status, 0, "cursed curl pod must fail");
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn both() {
|
||||
// In order to test the network policy, we need to create the client pod
|
||||
// before creating the authorization policy. To avoid races, we do this by
|
||||
// creating a `curl-lock` configmap that prevents curl from actually being
|
||||
// executed. Once nginx is running with the correct policy, the configmap is
|
||||
// deleted to unblock the curl pods.
|
||||
with_temp_ns(|client, ns| async move {
|
||||
let curl = curl::Runner::init(&client, &ns).await;
|
||||
curl.create_lock().await;
|
||||
|
||||
let (blessed_injected, blessed_uninjected) = tokio::join!(
|
||||
curl.run(
|
||||
"curl-blessed-injected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Enabled,
|
||||
),
|
||||
curl.run(
|
||||
"curl-blessed-uninjected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Disabled,
|
||||
)
|
||||
);
|
||||
let (blessed_injected_ip, blessed_uninjected_ip) =
|
||||
tokio::join!(blessed_injected.ip(), blessed_uninjected.ip(),);
|
||||
tracing::debug!(curl.blessed.injected.ip = ?blessed_injected_ip);
|
||||
tracing::debug!(curl.blessed.uninjected.ip = ?blessed_uninjected_ip);
|
||||
|
||||
// Once we know the IP of the (blocked) pod, create an nginx
|
||||
// authorization policy that permits connections from this pod.
|
||||
let (srv, allow_ips, all_mtls) = tokio::join!(
|
||||
create(&client, nginx::server(&ns)),
|
||||
create(
|
||||
&client,
|
||||
allow_ips(&ns, vec![blessed_injected_ip, blessed_uninjected_ip]),
|
||||
),
|
||||
create(&client, all_authenticated(&ns))
|
||||
);
|
||||
create(
|
||||
&client,
|
||||
authz_policy(
|
||||
&ns,
|
||||
"nginx",
|
||||
&srv,
|
||||
vec![
|
||||
NamespacedTargetRef::from_resource(&allow_ips),
|
||||
NamespacedTargetRef::from_resource(&all_mtls),
|
||||
],
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Start nginx with the policy.
|
||||
tokio::join!(
|
||||
create(&client, nginx::service(&ns)),
|
||||
create_ready_pod(&client, nginx::pod(&ns))
|
||||
);
|
||||
|
||||
// Once the nginx pod is ready, delete the `curl-lock` configmap to
|
||||
// unblock curl from running.
|
||||
curl.delete_lock().await;
|
||||
tracing::info!("unblocked curl");
|
||||
|
||||
let (blessed_injected_status, blessed_uninjected_status) =
|
||||
tokio::join!(blessed_injected.exit_code(), blessed_uninjected.exit_code());
|
||||
// The blessed and injected pod should be able to connect to the nginx pod.
|
||||
assert_eq!(
|
||||
blessed_injected_status, 0,
|
||||
"blessed injected curl pod must succeed"
|
||||
);
|
||||
// The blessed and uninjected pod should NOT be able to connect to the nginx pod.
|
||||
assert_ne!(
|
||||
blessed_uninjected_status, 0,
|
||||
"blessed uninjected curl pod must NOT succeed"
|
||||
);
|
||||
|
||||
let (cursed_injected, cursed_uninjected) = tokio::join!(
|
||||
curl.run(
|
||||
"curl-cursed-injected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Enabled,
|
||||
),
|
||||
curl.run(
|
||||
"curl-cursed-uninjected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Disabled,
|
||||
)
|
||||
);
|
||||
let (cursed_injected_status, cursed_uninjected_status) =
|
||||
tokio::join!(cursed_injected.exit_code(), cursed_uninjected.exit_code(),);
|
||||
assert_ne!(
|
||||
cursed_injected_status, 0,
|
||||
"cursed injected curl pod must fail"
|
||||
);
|
||||
assert_ne!(
|
||||
cursed_uninjected_status, 0,
|
||||
"cursed uninjected curl pod must fail"
|
||||
);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn either() {
|
||||
// In order to test the network policy, we need to create the client pod
|
||||
// before creating the authorization policy. To avoid races, we do this by
|
||||
// creating a `curl-lock` configmap that prevents curl from actually being
|
||||
// executed. Once nginx is running with the correct policy, the configmap is
|
||||
// deleted to unblock the curl pods.
|
||||
with_temp_ns(|client, ns| async move {
|
||||
let curl = curl::Runner::init(&client, &ns).await;
|
||||
curl.create_lock().await;
|
||||
|
||||
let (blessed_injected, blessed_uninjected) = tokio::join!(
|
||||
curl.run(
|
||||
"curl-blessed-injected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Enabled,
|
||||
),
|
||||
curl.run(
|
||||
"curl-blessed-uninjected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Disabled,
|
||||
)
|
||||
);
|
||||
let (blessed_injected_ip, blessed_uninjected_ip) =
|
||||
tokio::join!(blessed_injected.ip(), blessed_uninjected.ip());
|
||||
tracing::debug!(curl.blessed.injected.ip = ?blessed_injected_ip);
|
||||
tracing::debug!(curl.blessed.uninjected.ip = ?blessed_uninjected_ip);
|
||||
|
||||
// Once we know the IP of the (blocked) pod, create an nginx
|
||||
// authorization policy that permits connections from this pod.
|
||||
let (srv, allow_ips, all_mtls) = tokio::join!(
|
||||
create(&client, nginx::server(&ns)),
|
||||
create(&client, allow_ips(&ns, vec![blessed_uninjected_ip])),
|
||||
create(&client, all_authenticated(&ns))
|
||||
);
|
||||
tokio::join!(
|
||||
create(
|
||||
&client,
|
||||
authz_policy(
|
||||
&ns,
|
||||
"nginx-from-ip",
|
||||
&srv,
|
||||
vec![NamespacedTargetRef::from_resource(&allow_ips)],
|
||||
),
|
||||
),
|
||||
create(
|
||||
&client,
|
||||
authz_policy(
|
||||
&ns,
|
||||
"nginx-from-id",
|
||||
&srv,
|
||||
vec![NamespacedTargetRef::from_resource(&all_mtls)],
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Start nginx with the policy.
|
||||
tokio::join!(
|
||||
create(&client, nginx::service(&ns)),
|
||||
create_ready_pod(&client, nginx::pod(&ns)),
|
||||
);
|
||||
|
||||
// Once the nginx pod is ready, delete the `curl-lock` configmap to
|
||||
// unblock curl from running.
|
||||
curl.delete_lock().await;
|
||||
tracing::info!("unblocking curl");
|
||||
|
||||
let (blessed_injected_status, blessed_uninjected_status) =
|
||||
tokio::join!(blessed_injected.exit_code(), blessed_uninjected.exit_code());
|
||||
// The blessed and injected pod should be able to connect to the nginx pod.
|
||||
assert_eq!(
|
||||
blessed_injected_status, 0,
|
||||
"blessed injected curl pod must succeed"
|
||||
);
|
||||
// The blessed and uninjected pod should NOT be able to connect to the nginx pod.
|
||||
assert_eq!(
|
||||
blessed_uninjected_status, 0,
|
||||
"blessed uninjected curl pod must succeed"
|
||||
);
|
||||
|
||||
let (cursed_injected, cursed_uninjected) = tokio::join!(
|
||||
curl.run(
|
||||
"curl-cursed-injected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Enabled,
|
||||
),
|
||||
curl.run(
|
||||
"curl-cursed-uninjected",
|
||||
"http://nginx",
|
||||
LinkerdInject::Disabled,
|
||||
),
|
||||
);
|
||||
let (cursed_injected_status, cursed_uninjected_status) =
|
||||
tokio::join!(cursed_injected.exit_code(), cursed_uninjected.exit_code());
|
||||
assert_eq!(
|
||||
cursed_injected_status, 0,
|
||||
"cursed injected curl pod must succeed"
|
||||
);
|
||||
assert_ne!(
|
||||
cursed_uninjected_status, 0,
|
||||
"cursed uninjected curl pod must fail"
|
||||
);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
// === helpers ===
|
||||
|
||||
fn authz_policy(
|
||||
ns: &str,
|
||||
name: &str,
|
||||
target: &k8s::policy::Server,
|
||||
authns: impl IntoIterator<Item = NamespacedTargetRef>,
|
||||
) -> k8s::policy::AuthorizationPolicy {
|
||||
k8s::policy::AuthorizationPolicy {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::AuthorizationPolicySpec {
|
||||
target_ref: LocalTargetRef::from_resource(target),
|
||||
required_authentication_refs: authns.into_iter().collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn all_authenticated(ns: &str) -> k8s::policy::MeshTLSAuthentication {
|
||||
k8s::policy::MeshTLSAuthentication {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some("all-authenticated".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::MeshTLSAuthenticationSpec {
|
||||
identity_refs: None,
|
||||
identities: Some(vec!["*".to_string()]),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn allow_ips(
|
||||
ns: &str,
|
||||
ips: impl IntoIterator<Item = std::net::IpAddr>,
|
||||
) -> k8s::policy::NetworkAuthentication {
|
||||
k8s::policy::NetworkAuthentication {
|
||||
metadata: k8s::ObjectMeta {
|
||||
namespace: Some(ns.to_string()),
|
||||
name: Some("allow-pod".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: k8s::policy::NetworkAuthenticationSpec {
|
||||
networks: ips
|
||||
.into_iter()
|
||||
.map(|ip| k8s::policy::Network {
|
||||
cidr: ip.into(),
|
||||
except: None,
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue