Skip to content

Commit 074bf80

Browse files
authored
Merge pull request #60 from szuecs/platform-iam
Add support for Platform IAM tokens
2 parents d483b43 + 47c4966 commit 074bf80

3 files changed

Lines changed: 74 additions & 3 deletions

File tree

auth/tokens.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package auth
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"os"
7+
"path"
8+
9+
"golang.org/x/oauth2"
10+
"k8s.io/client-go/transport"
11+
)
12+
13+
const (
14+
DefaultCredentialsDir = "/meta/credentials"
15+
CredentialsDirEnvar = "CREDENTIALS_DIR"
16+
)
17+
18+
type platformCredentialsTokenSource struct {
19+
tokenName string
20+
credentialsDir string
21+
}
22+
23+
func NewPlatformCredentialsTokenSource(tokenName string, credentialsDir string) *platformCredentialsTokenSource {
24+
return &platformCredentialsTokenSource{
25+
tokenName: tokenName,
26+
credentialsDir: credentialsDir,
27+
}
28+
}
29+
30+
func (s *platformCredentialsTokenSource) Token() (*oauth2.Token, error) {
31+
filePath := path.Join(s.credentialsDir, fmt.Sprintf("%s-token-secret", s.tokenName))
32+
contents, err := os.ReadFile(filePath)
33+
if err != nil {
34+
return nil, err
35+
}
36+
return &oauth2.Token{AccessToken: string(contents)}, nil
37+
}
38+
39+
type tokenInjector struct {
40+
tokenSource oauth2.TokenSource
41+
next http.RoundTripper
42+
}
43+
44+
func TokenInjector(tokenSource oauth2.TokenSource) transport.WrapperFunc {
45+
return func(rt http.RoundTripper) http.RoundTripper {
46+
return &tokenInjector{
47+
tokenSource: tokenSource,
48+
next: rt,
49+
}
50+
}
51+
}
52+
53+
func (i *tokenInjector) RoundTrip(request *http.Request) (*http.Response, error) {
54+
token, err := i.tokenSource.Token()
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
60+
return i.next.RoundTrip(request)
61+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/prometheus/client_golang v1.20.4
1919
github.com/sirupsen/logrus v1.9.3
2020
github.com/stretchr/testify v1.10.0
21+
golang.org/x/oauth2 v0.27.0
2122
k8s.io/api v0.33.5
2223
k8s.io/apimachinery v0.33.5
2324
k8s.io/client-go v0.33.5
@@ -70,7 +71,6 @@ require (
7071
github.com/x448/float16 v0.8.4 // indirect
7172
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
7273
golang.org/x/net v0.38.0 // indirect
73-
golang.org/x/oauth2 v0.27.0 // indirect
7474
golang.org/x/sys v0.31.0 // indirect
7575
golang.org/x/term v0.30.0 // indirect
7676
golang.org/x/text v0.23.0 // indirect

main.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/aws/aws-sdk-go-v2/config"
1414
"github.com/prometheus/client_golang/prometheus/promhttp"
1515
log "github.com/sirupsen/logrus"
16+
"github.com/szuecs/kube-static-egress-controller/auth"
1617
"github.com/szuecs/kube-static-egress-controller/controller"
1718
"github.com/szuecs/kube-static-egress-controller/kube"
1819
"github.com/szuecs/kube-static-egress-controller/provider"
@@ -55,6 +56,9 @@ type Config struct {
5556
Namespace string
5657
ResyncInterval time.Duration
5758
Address string
59+
// required by Platform credentials
60+
UsePlatformCredentials bool
61+
CredentialsDir string
5862
}
5963

6064
var defaultConfig = &Config{
@@ -120,6 +124,8 @@ Example:
120124
// Flags related to Kubernetes
121125
app.Flag("master", "The Kubernetes API server to connect to (default: auto-detect)").Default(defaultConfig.Master).StringVar(&cfg.Master)
122126
app.Flag("kubeconfig", "Retrieve target cluster configuration from a Kubernetes configuration file (default: auto-detect)").Default(defaultConfig.KubeConfig).StringVar(&cfg.KubeConfig)
127+
app.Flag("use-platform-credentials", "Use Platform credentials (default: disabled)").BoolVar(&cfg.UsePlatformCredentials)
128+
app.Flag("credentials-dir", "Directory where the Platform credentials are stored (default: /meta/credentials)").Default(auth.DefaultCredentialsDir).Envar(auth.CredentialsDirEnvar).StringVar(&cfg.CredentialsDir)
123129
app.Flag("provider", "Provider implementing static egress <noop|aws> (default: auto-detect)").Default(defaultConfig.Provider).StringVar(&cfg.Provider)
124130
app.Flag("cluster-id", "Cluster ID used define ownership of Egress stack.").StringVar(&cfg.ClusterID)
125131
app.Flag("cluster-id-tag-prefix", "Prefix for the Cluster ID tag set on the Egress stack.").Default(defaultConfig.ClusterIDTagPrefix).StringVar(&cfg.ClusterIDTagPrefix)
@@ -169,7 +175,7 @@ func main() {
169175
}
170176

171177
configsChan := make(chan provider.EgressConfig)
172-
cmWatcher, err := kube.NewConfigMapWatcher(newKubeClient(), cfg.Namespace, "egress=static", configsChan)
178+
cmWatcher, err := kube.NewConfigMapWatcher(newKubeClient(cfg), cfg.Namespace, "egress=static", configsChan)
173179
if err != nil {
174180
log.Fatalf("Failed to setup ConfigMap watcher: %v", err)
175181
}
@@ -188,7 +194,7 @@ func main() {
188194
}
189195

190196
// newKubeClient returns a new Kubernetes client with the default config.
191-
func newKubeClient() kubernetes.Interface {
197+
func newKubeClient(cfg *Config) kubernetes.Interface {
192198
var kubeconfig string
193199
if _, err := os.Stat(clientcmd.RecommendedHomeFile); err == nil {
194200
kubeconfig = clientcmd.RecommendedHomeFile
@@ -199,6 +205,10 @@ func newKubeClient() kubernetes.Interface {
199205
log.Fatalf("build config failed: %v", err)
200206
}
201207

208+
if cfg.UsePlatformCredentials {
209+
config.Wrap(auth.TokenInjector(auth.NewPlatformCredentialsTokenSource(name, cfg.CredentialsDir)))
210+
}
211+
202212
client, err := kubernetes.NewForConfig(config)
203213
if err != nil {
204214
log.Fatalf("initialize kubernetes client failed: %v", err)

0 commit comments

Comments
 (0)