Skip to content

Commit bd57c70

Browse files
authored
API key via kubernetes secret (#402)
1 parent 53ff381 commit bd57c70

File tree

10 files changed

+121
-17
lines changed

10 files changed

+121
-17
lines changed

cloud/scope/clients.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,11 @@ type IBMVPCClients struct {
2828
//ServiceEndPoint string
2929
}
3030

31-
func (c *IBMVPCClients) setIBMVPCService(iamEndpoint string, svcEndpoint string, apiKey string) error {
31+
func (c *IBMVPCClients) setIBMVPCService(authenticator core.Authenticator, svcEndpoint string) error {
3232
var err error
3333
c.VPCService, err = vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
34-
Authenticator: &core.IamAuthenticator{
35-
ApiKey: apiKey,
36-
URL: iamEndpoint,
37-
},
38-
URL: svcEndpoint,
34+
Authenticator: authenticator,
35+
URL: svcEndpoint,
3936
})
4037

4138
return err

cloud/scope/cluster.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type ClusterScope struct {
5252
IBMVPCCluster *infrav1.IBMVPCCluster
5353
}
5454

55-
func NewClusterScope(params ClusterScopeParams, iamEndpoint string, apiKey string, svcEndpoint string) (*ClusterScope, error) {
55+
func NewClusterScope(params ClusterScopeParams, authenticator core.Authenticator, svcEndpoint string) (*ClusterScope, error) {
5656
if params.Cluster == nil {
5757
return nil, errors.New("failed to generate new scope from nil Cluster")
5858
}
@@ -69,7 +69,7 @@ func NewClusterScope(params ClusterScopeParams, iamEndpoint string, apiKey strin
6969
return nil, errors.Wrap(err, "failed to init patch helper")
7070
}
7171

72-
vpcErr := params.IBMVPCClients.setIBMVPCService(iamEndpoint, svcEndpoint, apiKey)
72+
vpcErr := params.IBMVPCClients.setIBMVPCService(authenticator, svcEndpoint)
7373
if vpcErr != nil {
7474
return nil, errors.Wrap(vpcErr, "failed to create IBM VPC session")
7575
}

cloud/scope/machine.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/go-logr/logr"
2424
"github.com/pkg/errors"
2525

26+
"github.com/IBM/go-sdk-core/v5/core"
2627
"github.com/IBM/vpc-go-sdk/vpcv1"
2728

2829
corev1 "k8s.io/api/core/v1"
@@ -58,7 +59,7 @@ type MachineScope struct {
5859
IBMVPCMachine *infrav1.IBMVPCMachine
5960
}
6061

61-
func NewMachineScope(params MachineScopeParams, iamEndpoint string, apiKey string, svcEndpoint string) (*MachineScope, error) {
62+
func NewMachineScope(params MachineScopeParams, authenticator core.Authenticator, svcEndpoint string) (*MachineScope, error) {
6263
if params.Machine == nil {
6364
return nil, errors.New("failed to generate new scope from nil Machine")
6465
}
@@ -75,7 +76,7 @@ func NewMachineScope(params MachineScopeParams, iamEndpoint string, apiKey strin
7576
return nil, errors.Wrap(err, "failed to init patch helper")
7677
}
7778

78-
vpcErr := params.IBMVPCClients.setIBMVPCService(iamEndpoint, svcEndpoint, apiKey)
79+
vpcErr := params.IBMVPCClients.setIBMVPCService(authenticator, svcEndpoint)
7980
if vpcErr != nil {
8081
return nil, errors.Wrap(vpcErr, "failed to create IBM VPC session")
8182
}

config/default/credentials.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: manager-bootstrap-credentials
5+
namespace: system
6+
type: Opaque
7+
stringData:
8+
ibm-credentials.env: |-
9+
IBMCLOUD_AUTH_TYPE=iam
10+
IBMCLOUD_APIKEY=${IBMCLOUD_API_KEY}
11+
IBMCLOUD_AUTH_URL=https://iam.cloud.ibm.com

config/default/kustomization.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ bases:
2424
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
2525
#- ../prometheus
2626

27+
resources:
28+
- credentials.yaml
29+
2730
patchesStrategicMerge:
2831
# Protect the /metrics endpoint by putting it behind auth.
2932
# If you want your controller-manager to expose the /metrics
3033
# endpoint w/o any authn/z, please comment the following line.
34+
- manager_credentials_patch.yaml
3135
- manager_auth_proxy_patch.yaml
3236
- manager_image_patch.yaml
3337

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: controller-manager
5+
namespace: system
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: manager
11+
env:
12+
- name: IBM_CREDENTIALS_FILE
13+
value: /home/.ibmcloud/ibm-credentials.env
14+
volumeMounts:
15+
- name: credentials
16+
mountPath: /home/.ibmcloud
17+
volumes:
18+
- name: credentials
19+
secret:
20+
secretName: manager-bootstrap-credentials

controllers/ibmvpccluster_controller.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737

3838
infrastructurev1alpha3 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1alpha3"
3939
"sigs.k8s.io/cluster-api-provider-ibmcloud/cloud/scope"
40+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg"
4041
)
4142

4243
// IBMVPCClusterReconciler reconciles a IBMVPCCluster object
@@ -75,16 +76,20 @@ func (r *IBMVPCClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reques
7576
}
7677

7778
// Create the scope.
78-
iamEndpoint := os.Getenv("IAM_ENDPOINT")
79-
apiKey := os.Getenv("API_KEY")
79+
// TODO: Will be removed once we find a better way of overriding the service endpoint, generate via spec
8080
svcEndpoint := os.Getenv("SERVICE_ENDPOINT")
8181

82+
authenticator, err := pkg.GetAuthenticator()
83+
if err != nil {
84+
return ctrl.Result{}, errors.Wrapf(err, "failed to get authenticator")
85+
}
86+
8287
clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{
8388
Client: r.Client,
8489
Logger: log,
8590
Cluster: cluster,
8691
IBMVPCCluster: ibmCluster,
87-
}, iamEndpoint, apiKey, svcEndpoint)
92+
}, authenticator, svcEndpoint)
8893

8994
// Always close the scope when exiting this function so we can persist any GCPMachine changes.
9095
defer func() {

controllers/ibmvpcmachine_controller.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838

3939
infrastructurev1alpha3 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1alpha3"
4040
"sigs.k8s.io/cluster-api-provider-ibmcloud/cloud/scope"
41+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg"
4142
)
4243

4344
// IBMVPCMachineReconciler reconciles a IBMVPCMachine object
@@ -97,10 +98,13 @@ func (r *IBMVPCMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques
9798
}
9899

99100
// Create the cluster scope
100-
iamEndpoint := os.Getenv("IAM_ENDPOINT")
101-
apiKey := os.Getenv("API_KEY")
102101
svcEndpoint := os.Getenv("SERVICE_ENDPOINT")
103102

103+
authenticator, err := pkg.GetAuthenticator()
104+
if err != nil {
105+
return ctrl.Result{}, errors.Wrapf(err, "failed to get authenticator")
106+
}
107+
104108
// Create the machine scope
105109
machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{
106110
Client: r.Client,
@@ -109,7 +113,7 @@ func (r *IBMVPCMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques
109113
IBMVPCCluster: ibmCluster,
110114
Machine: machine,
111115
IBMVPCMachine: ibmVpcMachine,
112-
}, iamEndpoint, apiKey, svcEndpoint)
116+
}, authenticator, svcEndpoint)
113117
if err != nil {
114118
return ctrl.Result{}, errors.Errorf("failed to create scope: %+v", err)
115119
}

pkg/authenticator.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pkg
18+
19+
import (
20+
"fmt"
21+
"github.com/IBM/go-sdk-core/v5/core"
22+
)
23+
24+
// This expects the credential file in the following search order:
25+
// 1) ${IBM_CREDENTIALS_FILE}
26+
// 2) <user-home-dir>/ibm-credentials.env
27+
// 3) <current-working-directory>/ibm-credentials.env
28+
//
29+
// and the format is:
30+
// $ cat ibm-credentials.env
31+
// IBMCLOUD_AUTH_TYPE=iam
32+
// IBMCLOUD_APIKEY=xxxxxxxxxxxxx
33+
// IBMCLOUD_AUTH_URL=https://iam.cloud.ibm.com
34+
35+
const (
36+
serviceIBMCloud = "IBMCLOUD"
37+
)
38+
39+
// GetAuthenticator instantiates an Authenticator from external config file
40+
func GetAuthenticator() (core.Authenticator, error) {
41+
auth, err := core.GetAuthenticatorFromEnvironment(serviceIBMCloud)
42+
if err != nil {
43+
return nil, err
44+
}
45+
switch auth.(type) {
46+
case *core.IamAuthenticator:
47+
return auth, nil
48+
default:
49+
return nil, fmt.Errorf("only IAM authenticator is supported")
50+
}
51+
}

pkg/client.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import (
2222

2323
"github.com/golang-jwt/jwt"
2424

25+
"github.com/IBM-Cloud/bluemix-go"
2526
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
2627
"github.com/IBM-Cloud/bluemix-go/authentication"
2728
"github.com/IBM-Cloud/bluemix-go/http"
2829
"github.com/IBM-Cloud/bluemix-go/rest"
2930
bxsession "github.com/IBM-Cloud/bluemix-go/session"
31+
"github.com/IBM/go-sdk-core/v5/core"
3032

3133
"k8s.io/klog/v2"
3234
)
@@ -98,7 +100,16 @@ func fetchUserDetails(sess *bxsession.Session, generation int) (*User, error) {
98100
func NewClient() *Client {
99101
c := &Client{}
100102

101-
bxSess, err := bxsession.New()
103+
authenticator, err := GetAuthenticator()
104+
if err != nil {
105+
klog.Fatal(err)
106+
}
107+
//TODO: this will be removed once power-go-client migrated to go-sdk-core
108+
auth, ok := authenticator.(*core.IamAuthenticator)
109+
if !ok {
110+
klog.Fatal("failed to assert the authenticator as IAM type, please check the ibm-credentials.env file")
111+
}
112+
bxSess, err := bxsession.New(&bluemix.Config{BluemixAPIKey: auth.ApiKey})
102113
if err != nil {
103114
klog.Fatal(err)
104115
}

0 commit comments

Comments
 (0)