-
Notifications
You must be signed in to change notification settings - Fork 7.6k
/
resource.go
121 lines (111 loc) · 5.15 KB
/
resource.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package credentials
import (
"fmt"
"strings"
"istio.io/istio/pkg/cluster"
)
const (
// KubernetesSecretType is the name of a SDS secret stored in Kubernetes. Secrets here take the form
// kubernetes://secret-name. They will be pulled from the same namespace and cluster as the requesting proxy lives in.
KubernetesSecretType = "kubernetes"
KubernetesSecretTypeURI = KubernetesSecretType + "://"
// KubernetesGatewaySecretType is the name of a SDS secret stored in Kubernetes, used by the gateway-api. Secrets here
// take the form kubernetes-gateway://namespace/name. They are pulled from the config cluster.
KubernetesGatewaySecretType = "kubernetes-gateway"
kubernetesGatewaySecretTypeURI = KubernetesGatewaySecretType + "://"
// BuiltinGatewaySecretType is the name of a SDS secret that uses the workloads own mTLS certificate
BuiltinGatewaySecretType = "builtin"
BuiltinGatewaySecretTypeURI = BuiltinGatewaySecretType + "://"
// SdsCaSuffix is the suffix of the sds resource name for root CA.
SdsCaSuffix = "-cacert"
)
// SecretResource defines a reference to a secret
type SecretResource struct {
// ResourceType is the type of secret. One of KubernetesSecretType or KubernetesGatewaySecretType
ResourceType string
// Name is the name of the secret
Name string
// Namespace is the namespace the secret resides in. For implicit namespace references (such as in KubernetesSecretType),
// this will be resolved to the appropriate namespace. As a result, this should never be empty.
Namespace string
// ResourceName is the original name of the resource
ResourceName string
// Cluster is the cluster the secret should be fetched from.
Cluster cluster.ID
}
func (sr SecretResource) Key() string {
return sr.ResourceType + "/" + sr.Name + "/" + sr.Namespace + "/" + string(sr.Cluster)
}
func (sr SecretResource) KubernetesResourceName() string {
return fmt.Sprintf("%s://%s/%s", sr.ResourceType, sr.Namespace, sr.Name)
}
func ToKubernetesGatewayResource(namespace, name string) string {
if strings.HasPrefix(name, BuiltinGatewaySecretTypeURI) {
return BuiltinGatewaySecretTypeURI
}
return fmt.Sprintf("%s://%s/%s", KubernetesGatewaySecretType, namespace, name)
}
// ToResourceName turns a `credentialName` into a resource name used for SDS
func ToResourceName(name string) string {
if strings.HasPrefix(name, BuiltinGatewaySecretTypeURI) {
return "default"
}
// If they explicitly defined the type, keep it
if strings.HasPrefix(name, KubernetesSecretTypeURI) || strings.HasPrefix(name, kubernetesGatewaySecretTypeURI) {
return name
}
// Otherwise, to kubernetes://
return KubernetesSecretTypeURI + name
}
// ParseResourceName parses a raw resourceName string.
func ParseResourceName(resourceName string, proxyNamespace string, proxyCluster cluster.ID, configCluster cluster.ID) (SecretResource, error) {
sep := "/"
if strings.HasPrefix(resourceName, KubernetesSecretTypeURI) {
// Valid formats:
// * kubernetes://secret-name
// * kubernetes://secret-namespace/secret-name
// If namespace is not set, we will fetch from the namespace of the proxy. The secret will be read from
// the cluster the proxy resides in. This mirrors the legacy behavior mounting a secret as a file
res := strings.TrimPrefix(resourceName, KubernetesSecretTypeURI)
split := strings.Split(res, sep)
namespace := proxyNamespace
name := split[0]
if len(split) > 1 {
namespace = split[0]
name = split[1]
}
return SecretResource{ResourceType: KubernetesSecretType, Name: name, Namespace: namespace, ResourceName: resourceName, Cluster: proxyCluster}, nil
} else if strings.HasPrefix(resourceName, kubernetesGatewaySecretTypeURI) {
// Valid formats:
// * kubernetes-gateway://secret-namespace/secret-name
// Namespace is required. The secret is read from the config cluster; this is the primary difference from KubernetesSecretType.
res := strings.TrimPrefix(resourceName, kubernetesGatewaySecretTypeURI)
split := strings.Split(res, sep)
if len(split) <= 1 {
return SecretResource{}, fmt.Errorf("invalid resource name %q. Expected namespace and name", resourceName)
}
namespace := split[0]
name := split[1]
if len(namespace) == 0 {
return SecretResource{}, fmt.Errorf("invalid resource name %q. Expected namespace", resourceName)
}
if len(name) == 0 {
return SecretResource{}, fmt.Errorf("invalid resource name %q. Expected name", resourceName)
}
return SecretResource{ResourceType: KubernetesGatewaySecretType, Name: name, Namespace: namespace, ResourceName: resourceName, Cluster: configCluster}, nil
}
return SecretResource{}, fmt.Errorf("unknown resource type: %v", resourceName)
}