Skip to content

Commit 7ee7d46

Browse files
authored
feat: Add ServiceAccount, ServiceAccountBinding, ApiKey (#305)
* add related api resources * feat: add apikeys, sa, sab * add to manager * make apikey and serviceaccount exposes secrets * fix lint * add spec.exportPlaintextToken
1 parent 1629fbc commit 7ee7d46

56 files changed

Lines changed: 6401 additions & 834 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ In this tutorial, a Kubernetes namespace called `test` is used for examples, whi
134134
- [ComputeWorkspace](docs/compute_workspace.md)
135135
- [ComputeFlinkDeployment](docs/compute_flink_deployment.md)
136136
- [StreamNative Cloud Secret](docs/secret.md)
137+
- [StreamNative Cloud APIKey](docs/apikey.md)
138+
- [StreamNative Cloud ServiceAccount](docs/serviceaccount.md)
139+
- [StreamNative Cloud ServiceAccountBinding](docs/serviceaccountbinding.md)
137140

138141
# Contributing
139142

api/v1alpha1/apikey_types.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2025 StreamNative
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+
package v1alpha1
16+
17+
import (
18+
corev1 "k8s.io/api/core/v1"
19+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20+
)
21+
22+
// APIKeySpec defines the desired state of APIKey
23+
type APIKeySpec struct {
24+
// APIServerRef is the reference to the StreamNativeCloudConnection
25+
// +required
26+
APIServerRef corev1.LocalObjectReference `json:"apiServerRef"`
27+
28+
// InstanceName is the name of the instance this API key is for
29+
// +optional
30+
InstanceName string `json:"instanceName,omitempty"`
31+
32+
// ServiceAccountName is the name of the service account this API key is for
33+
// +optional
34+
ServiceAccountName string `json:"serviceAccountName,omitempty"`
35+
36+
// Description is a user defined description of the key
37+
// +optional
38+
Description string `json:"description,omitempty"`
39+
40+
// ExpirationTime is a timestamp that defines when this API key will expire
41+
// This can only be set on initial creation and not updated later
42+
// +optional
43+
ExpirationTime *metav1.Time `json:"expirationTime,omitempty"`
44+
45+
// Revoke indicates whether this API key should be revoked
46+
// +optional
47+
Revoke bool `json:"revoke,omitempty"`
48+
49+
// EncryptionKey contains the public key used to encrypt the token
50+
// +optional
51+
EncryptionKey *EncryptionKey `json:"encryptionKey,omitempty"`
52+
53+
// ExportPlaintextToken indicates whether the token should be exported in plaintext
54+
// +optional
55+
ExportPlaintextToken *bool `json:"exportPlaintextToken,omitempty"`
56+
}
57+
58+
// EncryptionKey contains a public key used for encryption
59+
// +structType=atomic
60+
type EncryptionKey struct {
61+
// PEM is the public key in PEM format
62+
// +optional
63+
PEM string `json:"pem,omitempty"`
64+
}
65+
66+
// APIKeyStatus defines the observed state of APIKey
67+
type APIKeyStatus struct {
68+
// Conditions represent the latest available observations of an object's state
69+
// +optional
70+
Conditions []metav1.Condition `json:"conditions,omitempty"`
71+
72+
// ObservedGeneration is the last observed generation
73+
// +optional
74+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
75+
76+
// KeyID is a generated field that is a uid for the token
77+
// +optional
78+
KeyID *string `json:"keyId,omitempty"`
79+
80+
// IssuedAt is a timestamp of when the key was issued
81+
// +optional
82+
IssuedAt *metav1.Time `json:"issuedAt,omitempty"`
83+
84+
// ExpiresAt is a timestamp of when the key expires
85+
// +optional
86+
ExpiresAt *metav1.Time `json:"expiresAt,omitempty"`
87+
88+
// Token is the plaintext security token issued for the key
89+
// +optional
90+
Token *string `json:"token,omitempty"`
91+
92+
// EncryptedToken is the encrypted security token issued for the key
93+
// +optional
94+
EncryptedToken *EncryptedToken `json:"encryptedToken,omitempty"`
95+
96+
// RevokedAt is a timestamp of when the key was revoked, it triggers revocation action
97+
// +optional
98+
RevokedAt *metav1.Time `json:"revokedAt,omitempty"`
99+
}
100+
101+
// EncryptedToken is token that is encrypted using an encryption key
102+
// +structType=atomic
103+
type EncryptedToken struct {
104+
// JWE is the token as a JSON Web Encryption (JWE) message
105+
// For RSA public keys, the key encryption algorithm is RSA-OAEP, and the content encryption algorithm is AES GCM
106+
// +optional
107+
JWE *string `json:"jwe,omitempty"`
108+
}
109+
110+
//+kubebuilder:object:root=true
111+
//+kubebuilder:subresource:status
112+
//+kubebuilder:resource:scope=Namespaced,categories={streamnative,all}
113+
//+kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
114+
//+kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
115+
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
116+
117+
// APIKey is the Schema for the APIKeys API
118+
type APIKey struct {
119+
metav1.TypeMeta `json:",inline"`
120+
metav1.ObjectMeta `json:"metadata,omitempty"`
121+
122+
Spec APIKeySpec `json:"spec,omitempty"`
123+
Status APIKeyStatus `json:"status,omitempty"`
124+
}
125+
126+
//+kubebuilder:object:root=true
127+
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
128+
129+
// APIKeyList contains a list of APIKey
130+
type APIKeyList struct {
131+
metav1.TypeMeta `json:",inline"`
132+
metav1.ListMeta `json:"metadata,omitempty"`
133+
Items []APIKey `json:"items"`
134+
}
135+
136+
func init() {
137+
SchemeBuilder.Register(&APIKey{}, &APIKeyList{})
138+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2025 StreamNative
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+
package v1alpha1
16+
17+
import (
18+
corev1 "k8s.io/api/core/v1"
19+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20+
)
21+
22+
// ServiceAccountSpec defines the desired state of ServiceAccount
23+
type ServiceAccountSpec struct {
24+
// APIServerRef is the reference to the StreamNativeCloudConnection
25+
// +required
26+
APIServerRef corev1.LocalObjectReference `json:"apiServerRef"`
27+
}
28+
29+
// ServiceAccountStatus defines the observed state of ServiceAccount
30+
type ServiceAccountStatus struct {
31+
// Conditions represent the latest available observations of an object's state
32+
// +optional
33+
Conditions []metav1.Condition `json:"conditions,omitempty"`
34+
35+
// ObservedGeneration is the last observed generation
36+
// +optional
37+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
38+
39+
// PrivateKeyType indicates the type of private key information
40+
// +optional
41+
PrivateKeyType string `json:"privateKeyType,omitempty"`
42+
43+
// PrivateKeyData provides the private key data (in base-64 format) for authentication purposes
44+
// +optional
45+
PrivateKeyData string `json:"privateKeyData,omitempty"`
46+
}
47+
48+
//+kubebuilder:object:root=true
49+
//+kubebuilder:subresource:status
50+
//+kubebuilder:resource:scope=Namespaced,categories={streamnative,all}
51+
//+kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
52+
//+kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
53+
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
54+
55+
// ServiceAccount is the Schema for the ServiceAccounts API
56+
type ServiceAccount struct {
57+
metav1.TypeMeta `json:",inline"`
58+
metav1.ObjectMeta `json:"metadata,omitempty"`
59+
60+
Spec ServiceAccountSpec `json:"spec,omitempty"`
61+
Status ServiceAccountStatus `json:"status,omitempty"`
62+
}
63+
64+
//+kubebuilder:object:root=true
65+
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
66+
67+
// ServiceAccountList contains a list of ServiceAccount
68+
type ServiceAccountList struct {
69+
metav1.TypeMeta `json:",inline"`
70+
metav1.ListMeta `json:"metadata,omitempty"`
71+
Items []ServiceAccount `json:"items"`
72+
}
73+
74+
func init() {
75+
SchemeBuilder.Register(&ServiceAccount{}, &ServiceAccountList{})
76+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2025 StreamNative
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+
package v1alpha1
16+
17+
import (
18+
corev1 "k8s.io/api/core/v1"
19+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20+
)
21+
22+
// ServiceAccountBindingSpec defines the desired state of ServiceAccountBinding
23+
type ServiceAccountBindingSpec struct {
24+
// ServiceAccountName refers to the ServiceAccount under the same namespace as this binding object
25+
// +required
26+
ServiceAccountName string `json:"serviceAccountName"`
27+
28+
// APIServerRef is the reference to the StreamNativeCloudConnection
29+
// If not provided, it will be retrieved from the referenced ServiceAccount
30+
// +optional
31+
APIServerRef *corev1.LocalObjectReference `json:"apiServerRef,omitempty"`
32+
33+
// PoolMemberRefs refers to a list of PoolMembers in the current namespace or other namespaces
34+
// +required
35+
PoolMemberRefs []PoolMemberReference `json:"poolMemberRefs"`
36+
}
37+
38+
// ServiceAccountBindingStatus defines the observed state of ServiceAccountBinding
39+
type ServiceAccountBindingStatus struct {
40+
// Conditions represent the latest available observations of an object's state
41+
// +optional
42+
Conditions []metav1.Condition `json:"conditions,omitempty"`
43+
44+
// ObservedGeneration is the last observed generation
45+
// +optional
46+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
47+
}
48+
49+
//+kubebuilder:object:root=true
50+
//+kubebuilder:subresource:status
51+
//+kubebuilder:resource:scope=Namespaced,categories={streamnative,all}
52+
//+kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
53+
//+kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
54+
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
55+
56+
// ServiceAccountBinding is the Schema for the ServiceAccountBindings API
57+
type ServiceAccountBinding struct {
58+
metav1.TypeMeta `json:",inline"`
59+
metav1.ObjectMeta `json:"metadata,omitempty"`
60+
61+
Spec ServiceAccountBindingSpec `json:"spec,omitempty"`
62+
Status ServiceAccountBindingStatus `json:"status,omitempty"`
63+
}
64+
65+
//+kubebuilder:object:root=true
66+
//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
67+
68+
// ServiceAccountBindingList contains a list of ServiceAccountBinding
69+
type ServiceAccountBindingList struct {
70+
metav1.TypeMeta `json:",inline"`
71+
metav1.ListMeta `json:"metadata,omitempty"`
72+
Items []ServiceAccountBinding `json:"items"`
73+
}
74+
75+
func init() {
76+
SchemeBuilder.Register(&ServiceAccountBinding{}, &ServiceAccountBindingList{})
77+
}

0 commit comments

Comments
 (0)