2024-10-31 13:02:13 -04:00
/ *
Copyright 2024 The Kubernetes 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 plugin
import (
2025-07-08 21:28:11 -04:00
"fmt"
2024-10-31 13:02:13 -04:00
"sync"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/credentialprovider"
"k8s.io/kubernetes/pkg/features"
)
2025-07-08 21:28:11 -04:00
type dockerConfigProviderWithCoordinates interface {
// provideWithCoordinates returns the DockerConfig and service account coordinates for the given image.
provideWithCoordinates ( image string ) ( credentialprovider . DockerConfig , * credentialprovider . ServiceAccountCoordinates )
}
2024-10-31 13:02:13 -04:00
type provider struct {
name string
impl * pluginProvider
}
var providersMutex sync . RWMutex
var providers = make ( [ ] provider , 0 )
var seenProviderNames = sets . NewString ( )
func registerCredentialProviderPlugin ( name string , p * pluginProvider ) {
providersMutex . Lock ( )
defer providersMutex . Unlock ( )
if seenProviderNames . Has ( name ) {
2025-07-08 21:28:11 -04:00
panic ( fmt . Sprintf ( "Credential provider %q was registered twice" , name ) )
2024-10-31 13:02:13 -04:00
}
seenProviderNames . Insert ( name )
providers = append ( providers , provider { name , p } )
2025-08-11 18:22:46 -04:00
klog . V ( 4 ) . InfoS ( "Registered credential provider" , "provider" , name )
2024-10-31 13:02:13 -04:00
}
type externalCredentialProviderKeyring struct {
2025-07-08 21:28:11 -04:00
providers [ ] dockerConfigProviderWithCoordinates
2024-10-31 13:02:13 -04:00
}
func NewExternalCredentialProviderDockerKeyring ( podNamespace , podName , podUID , serviceAccountName string ) credentialprovider . DockerKeyring {
providersMutex . RLock ( )
defer providersMutex . RUnlock ( )
keyring := & externalCredentialProviderKeyring {
2025-07-08 21:28:11 -04:00
providers : make ( [ ] dockerConfigProviderWithCoordinates , 0 , len ( providers ) ) ,
2024-10-31 13:02:13 -04:00
}
for _ , p := range providers {
pp := & perPodPluginProvider {
provider : p . impl ,
}
if utilfeature . DefaultFeatureGate . Enabled ( features . KubeletServiceAccountTokenForCredentialProviders ) {
klog . V ( 4 ) . InfoS ( "Generating per pod credential provider" , "provider" , p . name , "podName" , podName , "podNamespace" , podNamespace , "podUID" , podUID , "serviceAccountName" , serviceAccountName )
pp . podNamespace = podNamespace
pp . podName = podName
pp . podUID = types . UID ( podUID )
pp . serviceAccountName = serviceAccountName
} else {
klog . V ( 4 ) . InfoS ( "Generating credential provider" , "provider" , p . name )
}
keyring . providers = append ( keyring . providers , pp )
}
return keyring
}
2024-10-16 09:45:01 -04:00
func ( k * externalCredentialProviderKeyring ) Lookup ( image string ) ( [ ] credentialprovider . TrackedAuthConfig , bool ) {
2024-10-31 13:02:13 -04:00
keyring := & credentialprovider . BasicDockerKeyring { }
for _ , p := range k . providers {
2025-07-08 21:28:11 -04:00
dockerConfig , saCoords := p . provideWithCoordinates ( image )
if saCoords != nil {
keyring . Add ( & credentialprovider . CredentialSource { ServiceAccount : saCoords } , dockerConfig )
} else {
keyring . Add ( nil , dockerConfig )
}
2024-10-31 13:02:13 -04:00
}
return keyring . Lookup ( image )
}