1 // Copyright 2020 Datawire. All rights reserved 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 /////////////////////////////////////////////////////////////////////////// 16 // Important: Run "make update-yaml" to regenerate code after modifying 17 // this file. 18 /////////////////////////////////////////////////////////////////////////// 19 20 package v2 21 22 import ( 23 corev1 "k8s.io/api/core/v1" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 ) 26 27 type ACMEProviderSpec struct { 28 // Specifies who to talk ACME with to get certs. Defaults to Let's 29 // Encrypt; if "none" (case-insensitive), do not try to do ACME for 30 // this Host. 31 Authority string `json:"authority,omitempty"` 32 Email string `json:"email,omitempty"` 33 34 // Specifies the Kubernetes Secret to use to store the private key of the ACME 35 // account (essentially, where to store the auto-generated password for the 36 // auto-created ACME account). You should not normally need to set this--the 37 // default value is based on a combination of the ACME authority being registered 38 // wit and the email address associated with the account. 39 // 40 // Note that this is a native-Kubernetes-style core.v1.LocalObjectReference, not 41 // an Ambassador-style `{name}.{namespace}` string. Because we're opinionated, it 42 // does not support referencing a Secret in another namespace (because most native 43 // Kubernetes resources don't support that), but if we ever abandon that opinion 44 // and decide to support non-local references it, it would be by adding a 45 // `namespace:` field by changing it from a core.v1.LocalObjectReference to a 46 // core.v1.SecretReference, not by adopting the `{name}.{namespace}` notation. 47 PrivateKeySecret *corev1.LocalObjectReference `json:"privateKeySecret,omitempty"` 48 49 // This is normally set automatically 50 Registration string `json:"registration,omitempty"` 51 } 52 53 type InsecureRequestPolicy struct { 54 // +kubebuilder:validation:Enum={"Redirect","Reject","Route"} 55 Action string `json:"action,omitempty"` 56 AdditionalPort *int `json:"additionalPort,omitempty"` 57 } 58 59 type RequestPolicy struct { 60 Insecure InsecureRequestPolicy `json:"insecure,omitempty"` 61 62 // Later we may define a 'secure' section too. 63 } 64 65 type PreviewURLSpec struct { 66 // Is the Preview URL feature enabled? 67 Enabled *bool `json:"enabled,omitempty"` 68 69 // What type of Preview URL is allowed? 70 Type PreviewURLType `json:"type,omitempty"` 71 } 72 73 // What type of Preview URL is allowed? 74 // 75 // - path 76 // - wildcard 77 // - datawire // FIXME rename this before release 78 // 79 // +kubebuilder:validation:Enum={"Path"} 80 type PreviewURLType string 81 82 // HostSpec defines the desired state of Host 83 type HostSpec struct { 84 // Common to all Ambassador objects (and optional). 85 AmbassadorID AmbassadorID `json:"ambassador_id,omitempty"` 86 // A compatibility alias for "ambassador_id"; because Host 87 // used to be specified with protobuf, and jsonpb allowed 88 // either "ambassador_id" or "ambassadorId", and even though 89 // we didn't tell people about "ambassadorId" it's what the 90 // web policy console generated because of jsonpb. So Hosts 91 // with 'ambassadorId' exist in the wild. 92 DeprecatedAmbassadorID AmbassadorID `json:"ambassadorId,omitempty"` 93 94 // Hostname by which the Ambassador can be reached. 95 Hostname string `json:"hostname,omitempty"` 96 97 // Selector by which we can find further configuration. Defaults to hostname=$hostname 98 // 99 // +k8s:conversion-gen:rename=MappingSelector 100 Selector *metav1.LabelSelector `json:"selector,omitempty"` 101 102 // Specifies whether/who to talk ACME with to automatically manage the $tlsSecret. 103 AcmeProvider *ACMEProviderSpec `json:"acmeProvider,omitempty"` 104 105 // Name of the Kubernetes secret into which to save generated 106 // certificates. If ACME is enabled (see $acmeProvider), then the 107 // default is $hostname; otherwise the default is "". If the value 108 // is "", then we do not do TLS for this Host. 109 TLSSecret *corev1.SecretReference `json:"tlsSecret,omitempty"` 110 111 // Request policy definition. 112 RequestPolicy *RequestPolicy `json:"requestPolicy,omitempty"` 113 114 // Configuration for the Preview URL feature of Service Preview. Defaults to preview URLs not enabled. 115 PreviewUrl *PreviewURLSpec `json:"previewUrl,omitempty"` 116 117 // Name of the TLSContext the Host resource is linked with. 118 // It is not valid to specify both `tlsContext` and `tls`. 119 // 120 // Note that this is a native-Kubernetes-style core.v1.LocalObjectReference, not 121 // an Ambassador-style `{name}.{namespace}` string. Because we're opinionated, it 122 // does not support referencing a Secret in another namespace (because most native 123 // Kubernetes resources don't support that), but if we ever abandon that opinion 124 // and decide to support non-local references it, it would be by adding a 125 // `namespace:` field by changing it from a core.v1.LocalObjectReference to a 126 // core.v1.SecretReference, not by adopting the `{name}.{namespace}` notation. 127 TLSContext *corev1.LocalObjectReference `json:"tlsContext,omitempty"` 128 129 // TLS configuration. It is not valid to specify both 130 // `tlsContext` and `tls`. 131 TLS *TLSConfig `json:"tls,omitempty"` 132 } 133 134 type TLSConfig struct { 135 CertChainFile string `json:"cert_chain_file,omitempty"` 136 PrivateKeyFile string `json:"private_key_file,omitempty"` 137 CASecret string `json:"ca_secret,omitempty"` 138 CAcertChainFile string `json:"cacert_chain_file,omitempty"` 139 AlpnProtocols string `json:"alpn_protocols,omitempty"` 140 CertRequired *bool `json:"cert_required,omitempty"` 141 MinTLSVersion string `json:"min_tls_version,omitempty"` 142 MaxTLSVersion string `json:"max_tls_version,omitempty"` 143 CipherSuites []string `json:"cipher_suites,omitempty"` 144 ECDHCurves []string `json:"ecdh_curves,omitempty"` 145 RedirectCleartextFrom *int `json:"redirect_cleartext_from,omitempty"` 146 SNI string `json:"sni,omitempty"` 147 148 // +k8s:conversion-gen:rename=CRLSecret 149 V3CRLSecret string `json:"v3CRLSecret,omitempty"` 150 } 151 152 // The first value listed in the Enum marker becomes the "zero" value, 153 // and it would be great if "Pending" could be the default value; but 154 // it's Important that the "zero" value be able to be shown as 155 // empty/omitted from display, and we really do want `kubectl get 156 // hosts` to say "Pending" in the "STATE" column, and not leave the 157 // column empty. 158 // 159 // +kubebuilder:validation:Type=string 160 // +kubebuilder:validation:Enum={"Initial","Pending","Ready","Error"} 161 type HostState int 162 163 // +kubebuilder:validation:Type=string 164 // +kubebuilder:validation:Enum={"NA","DefaultsFilled","ACMEUserPrivateKeyCreated","ACMEUserRegistered","ACMECertificateChallenge"} 165 type HostPhase int 166 167 // HostStatus defines the observed state of Host 168 type HostStatus struct { 169 TLSCertificateSource HostTLSCertificateSource `json:"tlsCertificateSource,omitempty"` 170 171 State HostState `json:"state,omitempty"` 172 173 // phaseCompleted and phasePending are valid when state==Pending or 174 // state==Error. 175 PhaseCompleted HostPhase `json:"phaseCompleted,omitempty"` 176 // phaseCompleted and phasePending are valid when state==Pending or 177 // state==Error. 178 PhasePending HostPhase `json:"phasePending,omitempty"` 179 180 // errorReason, errorTimestamp, and errorBackoff are valid when state==Error. 181 ErrorReason string `json:"errorReason,omitempty"` 182 ErrorTimestamp *metav1.Time `json:"errorTimestamp,omitempty"` 183 ErrorBackoff *metav1.Duration `json:"errorBackoff,omitempty"` 184 } 185 186 // +kubebuilder:validation:Enum={"Unknown","None","Other","ACME"} 187 type HostTLSCertificateSource string 188 189 // Host is the Schema for the hosts API 190 // 191 // +kubebuilder:object:root=true 192 // +kubebuilder:storageversion 193 // +kubebuilder:subresource:status 194 // +kubebuilder:printcolumn:name="Hostname",type=string,JSONPath=`.spec.hostname` 195 // +kubebuilder:printcolumn:name="State",type=string,JSONPath=`.status.state` 196 // +kubebuilder:printcolumn:name="Phase Completed",type=string,JSONPath=`.status.phaseCompleted` 197 // +kubebuilder:printcolumn:name="Phase Pending",type=string,JSONPath=`.status.phasePending` 198 // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` 199 type Host struct { 200 metav1.TypeMeta `json:""` 201 metav1.ObjectMeta `json:"metadata,omitempty"` 202 203 Spec *HostSpec `json:"spec,omitempty"` 204 Status HostStatus `json:"status,omitempty"` 205 } 206 207 // HostList contains a list of Hosts. 208 // 209 // +kubebuilder:object:root=true 210 type HostList struct { 211 metav1.TypeMeta `json:""` 212 metav1.ListMeta `json:"metadata,omitempty"` 213 Items []Host `json:"items"` 214 } 215 216 func init() { 217 SchemeBuilder.Register(&Host{}, &HostList{}) 218 } 219