@@ -10,74 +10,129 @@ import (
10
10
ocmcfg "github.com/openshift/rosa/pkg/config"
11
11
"github.com/openshift/rosa/pkg/ocm"
12
12
"github.com/sirupsen/logrus"
13
+ corev1 "k8s.io/api/core/v1"
14
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
15
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13
16
"sigs.k8s.io/controller-runtime/pkg/client"
14
17
15
18
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope"
19
+ "sigs.k8s.io/cluster-api-provider-aws/v2/util/system"
16
20
)
17
21
18
22
const (
19
- ocmTokenKey = "ocmToken"
20
- ocmAPIURLKey = "ocmApiUrl"
23
+ ocmTokenKey = "ocmToken"
24
+ ocmAPIURLKey = "ocmApiUrl"
25
+ ocmClientIDKey = "ocmClientID"
26
+ ocmClientSecretKey = "ocmClientSecret"
21
27
)
22
28
23
29
// NewOCMClient creates a new OCM client.
24
30
func NewOCMClient (ctx context.Context , rosaScope * scope.ROSAControlPlaneScope ) (* ocm.Client , error ) {
25
- token , url , err := ocmCredentials (ctx , rosaScope )
31
+ token , url , clientID , clientSecret , err := ocmCredentials (ctx , rosaScope )
26
32
if err != nil {
27
33
return nil , err
28
34
}
29
- return ocm .NewClient ().Logger (logrus .New ()).Config (& ocmcfg.Config {
30
- AccessToken : token ,
31
- URL : url ,
32
- }).Build ()
35
+
36
+ ocmConfig := ocmcfg.Config {
37
+ URL : url ,
38
+ }
39
+
40
+ if clientID != "" && clientSecret != "" {
41
+ ocmConfig .ClientID = clientID
42
+ ocmConfig .ClientSecret = clientSecret
43
+ } else if token != "" {
44
+ ocmConfig .AccessToken = token
45
+ }
46
+
47
+ return ocm .NewClient ().Logger (logrus .New ()).Config (& ocmConfig ).Build ()
33
48
}
34
49
35
50
func newOCMRawConnection (ctx context.Context , rosaScope * scope.ROSAControlPlaneScope ) (* sdk.Connection , error ) {
36
- logger , err := sdk .NewGoLoggerBuilder ().
51
+ ocmSdkLogger , err := sdk .NewGoLoggerBuilder ().
37
52
Debug (false ).
38
53
Build ()
39
54
if err != nil {
40
55
return nil , fmt .Errorf ("failed to build logger: %w" , err )
41
56
}
42
- token , url , err := ocmCredentials (ctx , rosaScope )
57
+
58
+ token , url , clientID , clientSecret , err := ocmCredentials (ctx , rosaScope )
43
59
if err != nil {
44
60
return nil , err
45
61
}
46
62
47
- connection , err := sdk .NewConnectionBuilder ().
48
- Logger (logger ).
49
- Tokens (token ).
50
- URL (url ).
51
- Build ()
63
+ connBuilder := sdk .NewConnectionBuilder ().
64
+ Logger (ocmSdkLogger ).
65
+ URL (url )
66
+
67
+ if clientID != "" && clientSecret != "" {
68
+ connBuilder .Client (clientID , clientSecret )
69
+ } else if token != "" {
70
+ connBuilder .Tokens (token )
71
+ }
72
+
73
+ connection , err := connBuilder .Build ()
52
74
if err != nil {
53
75
return nil , fmt .Errorf ("failed to create ocm connection: %w" , err )
54
76
}
55
77
56
78
return connection , nil
57
79
}
58
80
59
- func ocmCredentials (ctx context.Context , rosaScope * scope.ROSAControlPlaneScope ) (string , string , error ) {
60
- var token string
61
- var ocmAPIUrl string
81
+ func ocmCredentials (ctx context.Context , rosaScope * scope.ROSAControlPlaneScope ) (string , string , string , string , error ) {
82
+ var token string // Offline SSO token
83
+ var ocmClientID string // Service account client id
84
+ var ocmClientSecret string // Service account client secret
85
+ var ocmAPIUrl string // https://api.openshift.com by default
86
+ var secret * corev1.Secret
62
87
63
- secret : = rosaScope .CredentialsSecret ()
88
+ secret = rosaScope .CredentialsSecret () // We'll retrieve the OCM credentials ref from the ROSA control plane
64
89
if secret != nil {
65
90
if err := rosaScope .Client .Get (ctx , client .ObjectKeyFromObject (secret ), secret ); err != nil {
66
- return "" , "" , fmt .Errorf ("failed to get credentials secret: %w" , err )
91
+ return "" , "" , "" , "" , fmt .Errorf ("failed to get credentials secret: %w" , err )
67
92
}
93
+ } else { // If the reference to OCM secret wasn't specified in the ROSA control plane, we'll try to use a predefined secret name from the capa namespace
94
+ secret = & corev1.Secret {
95
+ ObjectMeta : metav1.ObjectMeta {
96
+ Name : "rosa-creds-secret" ,
97
+ Namespace : system .GetManagerNamespace (),
98
+ },
99
+ }
100
+
101
+ err := rosaScope .Client .Get (ctx , client .ObjectKeyFromObject (secret ), secret )
102
+ // We'll ignore non-existent secret so that we can try the ENV variable fallback below
103
+ // TODO: once the ENV variable fallback is gone, we can no longer ignore non-existent secret here
104
+ if err != nil && ! apierrors .IsNotFound (err ) {
105
+ return "" , "" , "" , "" , fmt .Errorf ("failed to get credentials secret: %w" , err )
106
+ }
107
+ }
108
+
109
+ token = string (secret .Data [ocmTokenKey ])
110
+ ocmAPIUrl = string (secret .Data [ocmAPIURLKey ])
111
+ ocmClientID = string (secret .Data [ocmClientIDKey ])
112
+ ocmClientSecret = string (secret .Data [ocmClientSecretKey ])
68
113
69
- token = string (secret .Data [ocmTokenKey ])
70
- ocmAPIUrl = string (secret .Data [ocmAPIURLKey ])
71
- } else {
72
- // fallback to env variables if secrert is not set
114
+ // Deprecation warning in case SSO offline token was used
115
+ if token != "" {
116
+ rosaScope .Info ("Using SSO offline token is deprecated, use service account credentials instead" )
117
+ }
118
+
119
+ if token == "" && (ocmClientID == "" || ocmClientSecret == "" ) {
120
+ // TODO: the ENV variables are to be removed with the next code release
121
+ // Last fall-back is to use OCM_TOKEN & OCM_API_URL environment variables (soon to be deprecated)
73
122
token = os .Getenv ("OCM_TOKEN" )
74
- if ocmAPIUrl = os .Getenv ("OCM_API_URL" ); ocmAPIUrl == "" {
75
- ocmAPIUrl = "https://api.openshift.com"
123
+ ocmAPIUrl = os .Getenv ("OCM_API_URL" )
124
+
125
+ if token != "" {
126
+ rosaScope .Info ("Defining OCM credentials in environment variable is deprecated, use secret with service account credentials instead" )
127
+ } else {
128
+ return "" , "" , "" , "" ,
129
+ fmt .Errorf ("OCM credentials have not been provided. Make sure to set the secret with service account credentials" )
76
130
}
77
131
}
78
132
79
- if token == "" {
80
- return "" , "" , fmt . Errorf ( "token is not provided, be sure to set OCM_TOKEN env variable or reference a credentials secret with key %s" , ocmTokenKey )
133
+ if ocmAPIUrl == "" {
134
+ ocmAPIUrl = "https://api.openshift.com" // Defaults to production URL
81
135
}
82
- return token , ocmAPIUrl , nil
136
+
137
+ return token , ocmAPIUrl , ocmClientID , ocmClientSecret , nil
83
138
}
0 commit comments