istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/credentials/resource.go (about) 1 // Copyright Istio Authors 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 credentials 16 17 import ( 18 "fmt" 19 "strings" 20 21 "istio.io/istio/pkg/cluster" 22 ) 23 24 const ( 25 // KubernetesSecretType is the name of a SDS secret stored in Kubernetes. Secrets here take the form 26 // kubernetes://secret-name. They will be pulled from the same namespace and cluster as the requesting proxy lives in. 27 KubernetesSecretType = "kubernetes" 28 KubernetesSecretTypeURI = KubernetesSecretType + "://" 29 // KubernetesGatewaySecretType is the name of a SDS secret stored in Kubernetes, used by the gateway-api. Secrets here 30 // take the form kubernetes-gateway://namespace/name. They are pulled from the config cluster. 31 KubernetesGatewaySecretType = "kubernetes-gateway" 32 kubernetesGatewaySecretTypeURI = KubernetesGatewaySecretType + "://" 33 // BuiltinGatewaySecretType is the name of a SDS secret that uses the workloads own mTLS certificate 34 BuiltinGatewaySecretType = "builtin" 35 BuiltinGatewaySecretTypeURI = BuiltinGatewaySecretType + "://" 36 // SdsCaSuffix is the suffix of the sds resource name for root CA. 37 SdsCaSuffix = "-cacert" 38 ) 39 40 // SecretResource defines a reference to a secret 41 type SecretResource struct { 42 // ResourceType is the type of secret. One of KubernetesSecretType or KubernetesGatewaySecretType 43 ResourceType string 44 // Name is the name of the secret 45 Name string 46 // Namespace is the namespace the secret resides in. For implicit namespace references (such as in KubernetesSecretType), 47 // this will be resolved to the appropriate namespace. As a result, this should never be empty. 48 Namespace string 49 // ResourceName is the original name of the resource 50 ResourceName string 51 // Cluster is the cluster the secret should be fetched from. 52 Cluster cluster.ID 53 } 54 55 func (sr SecretResource) Key() string { 56 return sr.ResourceType + "/" + sr.Name + "/" + sr.Namespace + "/" + string(sr.Cluster) 57 } 58 59 func (sr SecretResource) KubernetesResourceName() string { 60 return fmt.Sprintf("%s://%s/%s", sr.ResourceType, sr.Namespace, sr.Name) 61 } 62 63 func ToKubernetesGatewayResource(namespace, name string) string { 64 if strings.HasPrefix(name, BuiltinGatewaySecretTypeURI) { 65 return BuiltinGatewaySecretTypeURI 66 } 67 return fmt.Sprintf("%s://%s/%s", KubernetesGatewaySecretType, namespace, name) 68 } 69 70 // ToResourceName turns a `credentialName` into a resource name used for SDS 71 func ToResourceName(name string) string { 72 if strings.HasPrefix(name, BuiltinGatewaySecretTypeURI) { 73 return "default" 74 } 75 // If they explicitly defined the type, keep it 76 if strings.HasPrefix(name, KubernetesSecretTypeURI) || strings.HasPrefix(name, kubernetesGatewaySecretTypeURI) { 77 return name 78 } 79 // Otherwise, to kubernetes:// 80 return KubernetesSecretTypeURI + name 81 } 82 83 // ParseResourceName parses a raw resourceName string. 84 func ParseResourceName(resourceName string, proxyNamespace string, proxyCluster cluster.ID, configCluster cluster.ID) (SecretResource, error) { 85 sep := "/" 86 if strings.HasPrefix(resourceName, KubernetesSecretTypeURI) { 87 // Valid formats: 88 // * kubernetes://secret-name 89 // * kubernetes://secret-namespace/secret-name 90 // If namespace is not set, we will fetch from the namespace of the proxy. The secret will be read from 91 // the cluster the proxy resides in. This mirrors the legacy behavior mounting a secret as a file 92 res := strings.TrimPrefix(resourceName, KubernetesSecretTypeURI) 93 split := strings.Split(res, sep) 94 namespace := proxyNamespace 95 name := split[0] 96 if len(split) > 1 { 97 namespace = split[0] 98 name = split[1] 99 } 100 return SecretResource{ResourceType: KubernetesSecretType, Name: name, Namespace: namespace, ResourceName: resourceName, Cluster: proxyCluster}, nil 101 } else if strings.HasPrefix(resourceName, kubernetesGatewaySecretTypeURI) { 102 // Valid formats: 103 // * kubernetes-gateway://secret-namespace/secret-name 104 // Namespace is required. The secret is read from the config cluster; this is the primary difference from KubernetesSecretType. 105 res := strings.TrimPrefix(resourceName, kubernetesGatewaySecretTypeURI) 106 split := strings.Split(res, sep) 107 if len(split) <= 1 { 108 return SecretResource{}, fmt.Errorf("invalid resource name %q. Expected namespace and name", resourceName) 109 } 110 namespace := split[0] 111 name := split[1] 112 if len(namespace) == 0 { 113 return SecretResource{}, fmt.Errorf("invalid resource name %q. Expected namespace", resourceName) 114 } 115 if len(name) == 0 { 116 return SecretResource{}, fmt.Errorf("invalid resource name %q. Expected name", resourceName) 117 } 118 return SecretResource{ResourceType: KubernetesGatewaySecretType, Name: name, Namespace: namespace, ResourceName: resourceName, Cluster: configCluster}, nil 119 } 120 return SecretResource{}, fmt.Errorf("unknown resource type: %v", resourceName) 121 }