k8s-operator,cmd/k8s-operator: define ProxyGroupPolicy CRD (#18614)
This commit adds a new custom resource definition to the kubernetes operator named `ProxyGroupPolicy`. This resource is namespace scoped and is used as an allow list for which `ProxyGroup` resources can be used within its namespace. The `spec` contains two fields, `ingress` and `egress`. These should contain the names of `ProxyGroup` resources to denote which can be used as values in the `tailscale.com/proxy-group` annotation within `Service` and `Ingress` resources. The intention is for these policies to be merged within a namespace and produce a `ValidatingAdmissionPolicy` and `ValidatingAdmissionPolicyBinding` for both ingress and egress that prevents users from using names of `ProxyGroup` resources in those annotations. Closes: https://github.com/tailscale/corp/issues/36829 Signed-off-by: David Bond <davidsbond93@gmail.com>main
parent
d468870310
commit
a341eea00b
@ -0,0 +1,139 @@ |
||||
apiVersion: apiextensions.k8s.io/v1 |
||||
kind: CustomResourceDefinition |
||||
metadata: |
||||
annotations: |
||||
controller-gen.kubebuilder.io/version: v0.17.0 |
||||
name: proxygrouppolicies.tailscale.com |
||||
spec: |
||||
group: tailscale.com |
||||
names: |
||||
kind: ProxyGroupPolicy |
||||
listKind: ProxyGroupPolicyList |
||||
plural: proxygrouppolicies |
||||
shortNames: |
||||
- pgp |
||||
singular: proxygrouppolicy |
||||
scope: Namespaced |
||||
versions: |
||||
- additionalPrinterColumns: |
||||
- jsonPath: .metadata.creationTimestamp |
||||
name: Age |
||||
type: date |
||||
- description: Status of the deployed ProxyGroupPolicy resources. |
||||
jsonPath: .status.conditions[?(@.type == "ProxyGroupPolicyReady")].reason |
||||
name: Status |
||||
type: string |
||||
name: v1alpha1 |
||||
schema: |
||||
openAPIV3Schema: |
||||
type: object |
||||
required: |
||||
- metadata |
||||
- spec |
||||
properties: |
||||
apiVersion: |
||||
description: |- |
||||
APIVersion defines the versioned schema of this representation of an object. |
||||
Servers should convert recognized schemas to the latest internal value, and |
||||
may reject unrecognized values. |
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources |
||||
type: string |
||||
kind: |
||||
description: |- |
||||
Kind is a string value representing the REST resource this object represents. |
||||
Servers may infer this from the endpoint the client submits requests to. |
||||
Cannot be updated. |
||||
In CamelCase. |
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds |
||||
type: string |
||||
metadata: |
||||
type: object |
||||
spec: |
||||
description: |- |
||||
Spec describes the desired state of the ProxyGroupPolicy. |
||||
More info: |
||||
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status |
||||
type: object |
||||
properties: |
||||
egress: |
||||
description: |- |
||||
Names of ProxyGroup resources that can be used by Service resources within this namespace. An empty list |
||||
denotes that no egress via ProxyGroups is allowed within this namespace. |
||||
type: array |
||||
items: |
||||
type: string |
||||
ingress: |
||||
description: |- |
||||
Names of ProxyGroup resources that can be used by Ingress resources within this namespace. An empty list |
||||
denotes that no ingress via ProxyGroups is allowed within this namespace. |
||||
type: array |
||||
items: |
||||
type: string |
||||
status: |
||||
description: |- |
||||
Status describes the status of the ProxyGroupPolicy. This is set |
||||
and managed by the Tailscale operator. |
||||
type: object |
||||
properties: |
||||
conditions: |
||||
type: array |
||||
items: |
||||
description: Condition contains details for one aspect of the current state of this API Resource. |
||||
type: object |
||||
required: |
||||
- lastTransitionTime |
||||
- message |
||||
- reason |
||||
- status |
||||
- type |
||||
properties: |
||||
lastTransitionTime: |
||||
description: |- |
||||
lastTransitionTime is the last time the condition transitioned from one status to another. |
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. |
||||
type: string |
||||
format: date-time |
||||
message: |
||||
description: |- |
||||
message is a human readable message indicating details about the transition. |
||||
This may be an empty string. |
||||
type: string |
||||
maxLength: 32768 |
||||
observedGeneration: |
||||
description: |- |
||||
observedGeneration represents the .metadata.generation that the condition was set based upon. |
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date |
||||
with respect to the current state of the instance. |
||||
type: integer |
||||
format: int64 |
||||
minimum: 0 |
||||
reason: |
||||
description: |- |
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition. |
||||
Producers of specific condition types may define expected values and meanings for this field, |
||||
and whether the values are considered a guaranteed API. |
||||
The value should be a CamelCase string. |
||||
This field may not be empty. |
||||
type: string |
||||
maxLength: 1024 |
||||
minLength: 1 |
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ |
||||
status: |
||||
description: status of the condition, one of True, False, Unknown. |
||||
type: string |
||||
enum: |
||||
- "True" |
||||
- "False" |
||||
- Unknown |
||||
type: |
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase. |
||||
type: string |
||||
maxLength: 316 |
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ |
||||
x-kubernetes-list-map-keys: |
||||
- type |
||||
x-kubernetes-list-type: map |
||||
served: true |
||||
storage: true |
||||
subresources: |
||||
status: {} |
||||
@ -0,0 +1,67 @@ |
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !plan9
|
||||
|
||||
package v1alpha1 |
||||
|
||||
import ( |
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||
) |
||||
|
||||
// Code comments on these types should be treated as user facing documentation-
|
||||
// they will appear on the ProxyGroupPolicy CRD i.e. if someone runs kubectl explain tailnet.
|
||||
|
||||
var ProxyGroupPolicyKind = "ProxyGroupPolicy" |
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:scope=Namespaced,shortName=pgp
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
|
||||
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=`.status.conditions[?(@.type == "ProxyGroupPolicyReady")].reason`,description="Status of the deployed ProxyGroupPolicy resources."
|
||||
|
||||
type ProxyGroupPolicy struct { |
||||
metav1.TypeMeta `json:",inline"` |
||||
metav1.ObjectMeta `json:"metadata,omitzero"` |
||||
|
||||
// Spec describes the desired state of the ProxyGroupPolicy.
|
||||
// More info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
|
||||
Spec ProxyGroupPolicySpec `json:"spec"` |
||||
|
||||
// Status describes the status of the ProxyGroupPolicy. This is set
|
||||
// and managed by the Tailscale operator.
|
||||
// +optional
|
||||
Status ProxyGroupPolicyStatus `json:"status"` |
||||
} |
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
type ProxyGroupPolicyList struct { |
||||
metav1.TypeMeta `json:",inline"` |
||||
metav1.ListMeta `json:"metadata"` |
||||
|
||||
Items []ProxyGroupPolicy `json:"items"` |
||||
} |
||||
|
||||
type ProxyGroupPolicySpec struct { |
||||
// Names of ProxyGroup resources that can be used by Ingress resources within this namespace. An empty list
|
||||
// denotes that no ingress via ProxyGroups is allowed within this namespace.
|
||||
// +optional
|
||||
Ingress []string `json:"ingress,omitempty"` |
||||
|
||||
// Names of ProxyGroup resources that can be used by Service resources within this namespace. An empty list
|
||||
// denotes that no egress via ProxyGroups is allowed within this namespace.
|
||||
// +optional
|
||||
Egress []string `json:"egress,omitempty"` |
||||
} |
||||
|
||||
type ProxyGroupPolicyStatus struct { |
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions"` |
||||
} |
||||
|
||||
// ProxyGroupPolicyReady is set to True if the ProxyGroupPolicy is available for use by operator workloads.
|
||||
const ProxyGroupPolicyReady ConditionType = "ProxyGroupPolicyReady" |
||||
Loading…
Reference in new issue