Skip to content

Commit d765320

Browse files
authored
Support Trusted profile name for assume authentication (#6479)
1 parent 018e288 commit d765320

File tree

5 files changed

+218
-157
lines changed

5 files changed

+218
-157
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/IBM-Cloud/terraform-provider-ibm
33
go 1.24.2
44

55
require (
6-
github.com/IBM-Cloud/bluemix-go v0.0.0-20250912140913-e279174fe80b
6+
github.com/IBM-Cloud/bluemix-go v0.0.0-20250925065941-e1953cea5812
77
github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113
88
github.com/IBM-Cloud/power-go-client v1.13.0
99
github.com/IBM/appconfiguration-go-admin-sdk v0.5.1
@@ -206,7 +206,7 @@ require (
206206
golang.org/x/net v0.43.0 // indirect
207207
golang.org/x/oauth2 v0.27.0 // indirect
208208
golang.org/x/sync v0.16.0 // indirect
209-
golang.org/x/sys v0.35.0 // indirect
209+
golang.org/x/sys v0.36.0 // indirect
210210
golang.org/x/term v0.34.0 // indirect
211211
golang.org/x/text v0.28.0 // indirect
212212
golang.org/x/time v0.9.0 // indirect

go.sum

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0
9090
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
9191
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
9292
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
93-
github.com/IBM-Cloud/bluemix-go v0.0.0-20250912140913-e279174fe80b h1:KvUKPR6fCkByNcaXf1DWoWDjjqK5zj9f6gzhK1cc4PQ=
94-
github.com/IBM-Cloud/bluemix-go v0.0.0-20250912140913-e279174fe80b/go.mod h1:uqxINL7UuXasMI5Y3yGBh5izcsIksdIGxgQ78oM+5Dk=
93+
github.com/IBM-Cloud/bluemix-go v0.0.0-20250925065941-e1953cea5812 h1:f6jfPxYeSWh5u3ZM7cIz5kDlSILtuN6LAGgnS9TUbvg=
94+
github.com/IBM-Cloud/bluemix-go v0.0.0-20250925065941-e1953cea5812/go.mod h1:lU1/3aolIs4y062yTTokFEiIEssAZqqjdj/5qvkBeq8=
9595
github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113 h1:f2Erqfea1dKpaTFagTJM6W/wnD3JGq/Vn9URh8nuRwk=
9696
github.com/IBM-Cloud/container-services-go-sdk v0.0.0-20240725064144-454a2ae23113/go.mod h1:xUQL9SGAjoZFd4GNjrjjtEpjpkgU7RFXRyHesbKTjiY=
9797
github.com/IBM-Cloud/power-go-client v1.13.0 h1:TqxPlkJe0VkNdV9hYOD5NRepxEFhhyKXWXfg22x2zhU=
@@ -169,8 +169,6 @@ github.com/IBM/vmware-go-sdk v0.1.5 h1:aQbwcJBceaaauuIoJ0OJn+ttwjb+QTX6XV9Jbrdpj
169169
github.com/IBM/vmware-go-sdk v0.1.5/go.mod h1:OyQKRInGGsBaOyE5LIZCqH7b1DZ01BvIYa8BgGy+wWo=
170170
github.com/IBM/vpc-beta-go-sdk v0.8.0 h1:cEPpv4iw3Ba5W2d0AWg3TIbKeJ8y1nPuUuibR5Jt9eE=
171171
github.com/IBM/vpc-beta-go-sdk v0.8.0/go.mod h1:hORgIyTFRzXrZIK9IohaWmCRBBlYiDRagsufi7M6akE=
172-
github.com/IBM/vpc-go-sdk v0.72.0 h1:3Pj7nNuYmlaRPiMyC/5Uro3+5hzNBM6v2Lrq5UABBkQ=
173-
github.com/IBM/vpc-go-sdk v0.72.0/go.mod h1:K3vVlje72PYE3ZRt1iouE+jSIq+vCyYzT1HiFC06hUA=
174172
github.com/IBM/vpc-go-sdk v0.73.0 h1:gMVR6NSzw8Y7pCkcDa92+heQTzu5X64q8bnBBpLJpFE=
175173
github.com/IBM/vpc-go-sdk v0.73.0/go.mod h1:K3vVlje72PYE3ZRt1iouE+jSIq+vCyYzT1HiFC06hUA=
176174
github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0=
@@ -1603,8 +1601,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
16031601
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
16041602
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
16051603
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1606-
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
1607-
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
1604+
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
1605+
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
16081606
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
16091607
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
16101608
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

ibm/conns/config.go

Lines changed: 125 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ import (
140140
// RetryAPIDelay - retry api delay
141141
const RetryAPIDelay = 5 * time.Second
142142

143+
const IAMURL = iamidentity.DefaultServiceURL
144+
143145
// BluemixRegion ...
144146
var BluemixRegion string
145147

@@ -198,9 +200,15 @@ type Config struct {
198200
// IAM Token
199201
IAMToken string
200202

201-
// TrustedProfileToken Token
203+
// TrustedProfileID
202204
IAMTrustedProfileID string
203205

206+
// TrustedProfileName
207+
IAMTrustedProfileName string
208+
209+
// Account
210+
Account string
211+
204212
// IAM Refresh Token
205213
IAMRefreshToken string
206214

@@ -1449,62 +1457,22 @@ func (c *Config) ClientSession() (interface{}, error) {
14491457
return session, nil
14501458
}
14511459

1452-
if sess.BluemixSession.Config.BluemixAPIKey != "" && c.IAMTrustedProfileID == "" {
1453-
err = authenticateAPIKey(sess.BluemixSession)
1454-
if err != nil {
1455-
for count := c.RetryCount; count >= 0; count-- {
1456-
if err == nil || !isRetryable(err) {
1457-
break
1458-
}
1459-
time.Sleep(c.RetryDelay)
1460-
log.Printf("Retrying IAM Authentication %d", count)
1461-
err = authenticateAPIKey(sess.BluemixSession)
1462-
}
1463-
if err != nil {
1464-
session.bmxUserFetchErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for account user details: %q", err)
1465-
session.functionConfigErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for function: %q", err)
1460+
err = fetchAuthorizationData(sess.BluemixSession)
1461+
if err != nil {
1462+
for count := c.RetryCount; count >= 0; count-- {
1463+
if err == nil || !isRetryable(err) {
1464+
break
14661465
}
1466+
time.Sleep(c.RetryDelay)
1467+
log.Printf("Retrying IAM Authentication %d", count)
1468+
err = fetchAuthorizationData(sess.BluemixSession)
14671469
}
1468-
1469-
session.functionConfigErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for function: %q", err)
1470-
}
1471-
1472-
if sess.BluemixSession.Config.BluemixAPIKey != "" && c.IAMTrustedProfileID != "" {
1473-
err = authenticateAssume(sess.BluemixSession)
14741470
if err != nil {
1475-
for count := c.RetryCount; count >= 0; count-- {
1476-
if err == nil || !isRetryable(err) {
1477-
break
1478-
}
1479-
time.Sleep(c.RetryDelay)
1480-
log.Printf("Retrying IAM Authentication %d", count)
1481-
err = authenticateAssume(sess.BluemixSession)
1482-
}
1483-
if err != nil {
1484-
session.bmxUserFetchErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for account user details: %q", err)
1485-
session.functionConfigErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for function: %q", err)
1486-
}
1471+
session.bmxUserFetchErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for account user details: %q", err)
1472+
session.functionConfigErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for function: %q", err)
14871473
}
1488-
1489-
session.functionConfigErr = fmt.Errorf("[ERROR] Error occured while fetching auth key for function: %q", err)
14901474
}
14911475

1492-
if c.IAMTrustedProfileID == "" && sess.BluemixSession.Config.BluemixAPIKey == "" && sess.BluemixSession.Config.IAMAccessToken != "" && sess.BluemixSession.Config.IAMRefreshToken != "" {
1493-
err := RefreshToken(sess.BluemixSession)
1494-
if err != nil {
1495-
for count := c.RetryCount; count >= 0; count-- {
1496-
if err == nil || !isRetryable(err) {
1497-
break
1498-
}
1499-
time.Sleep(c.RetryDelay)
1500-
log.Printf("Retrying refresh token %d", count)
1501-
err = RefreshToken(sess.BluemixSession)
1502-
}
1503-
if err != nil {
1504-
return nil, fmt.Errorf("[ERROR] Error occured while refreshing the token: %q", err)
1505-
}
1506-
}
1507-
}
15081476
userConfig, err := fetchUserDetails(sess.BluemixSession, c.RetryCount, c.RetryDelay)
15091477
if err != nil {
15101478
session.bmxUserFetchErr = fmt.Errorf("[ERROR] Error occured while fetching account user details: %q", err)
@@ -1601,7 +1569,8 @@ func (c *Config) ClientSession() (interface{}, error) {
16011569
}
16021570
session.kpAPI = kpAPIclient
16031571

1604-
iamURL := iamidentity.DefaultServiceURL
1572+
iamURL := EnvFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, IAMURL)
1573+
16051574
if c.Visibility == "private" || c.Visibility == "public-and-private" {
16061575
if c.Region == "us-south" || c.Region == "us-east" {
16071576
iamURL = ContructEndpoint(fmt.Sprintf("private.%s.iam", c.Region), cloudEndpoint)
@@ -1647,13 +1616,25 @@ func (c *Config) ClientSession() (interface{}, error) {
16471616

16481617
var authenticator core.Authenticator
16491618

1650-
if (c.BluemixAPIKey != "") && c.IAMTrustedProfileID != "" {
1651-
authenticator, err = core.NewIamAssumeAuthenticatorBuilder().
1652-
SetApiKey(c.BluemixAPIKey).
1653-
SetIAMProfileID(c.IAMTrustedProfileID).
1654-
Build()
1655-
if err != nil {
1656-
log.Fatalf("Error in authenticating using NewIamAssumeAuthenticatorBuilder. Error: %s", err)
1619+
if (c.BluemixAPIKey != "") && (c.IAMTrustedProfileID != "" || c.IAMTrustedProfileName != "") {
1620+
if c.IAMTrustedProfileID != "" {
1621+
authenticator, err = core.NewIamAssumeAuthenticatorBuilder().
1622+
SetApiKey(c.BluemixAPIKey).
1623+
SetIAMProfileID(c.IAMTrustedProfileID).
1624+
Build()
1625+
if err != nil {
1626+
log.Fatalf("Error in authenticating using NewIamAssumeAuthenticatorBuilder. Error: %s", err)
1627+
}
1628+
} else {
1629+
authenticator, err = core.NewIamAssumeAuthenticatorBuilder().
1630+
SetApiKey(c.BluemixAPIKey).
1631+
SetIAMProfileName(c.IAMTrustedProfileName).
1632+
SetIAMAccountID(c.Account).
1633+
Build()
1634+
if err != nil {
1635+
log.Fatalf("Error in authenticating using NewIamAssumeAuthenticatorBuilder with trusted profile name. Error: %s", err)
1636+
}
1637+
16571638
}
16581639
} else if c.BluemixAPIKey != "" || sess.BluemixSession.Config.IAMRefreshToken != "" {
16591640
if c.BluemixAPIKey != "" {
@@ -3799,67 +3780,83 @@ func newSession(c *Config) (*Session, error) {
37993780
softlayerSession.AppendUserAgent(fmt.Sprintf("terraform-provider-ibm/%s", version.Version))
38003781
ibmSession.SoftLayerSession = softlayerSession
38013782

3802-
/*if c.IAMTrustedProfileID == "" && (c.IAMToken != "" && c.IAMRefreshToken == "") || (c.IAMToken == "" && c.IAMRefreshToken != "") {
3803-
return nil, fmt.Errorf("iam_token and iam_refresh_token must be provided")
3804-
}
3805-
if c.IAMTrustedProfileID != "" && c.IAMToken == "" {
3806-
return nil, fmt.Errorf("iam_token and iam_profile_id must be provided")
3807-
}*/
3808-
3809-
if c.IAMToken != "" {
3810-
log.Println("Configuring IBM Cloud Session with token")
3811-
var sess *bxsession.Session
3812-
bmxConfig := &bluemix.Config{
3813-
IAMAccessToken: c.IAMToken,
3814-
IAMRefreshToken: c.IAMRefreshToken,
3815-
// Comment out debug mode for v0.12
3816-
Debug: os.Getenv("TF_LOG") != "",
3817-
HTTPTimeout: c.BluemixTimeout,
3818-
Region: c.Region,
3819-
ResourceGroup: c.ResourceGroup,
3820-
RetryDelay: &c.RetryDelay,
3821-
MaxRetries: &c.RetryCount,
3822-
Visibility: c.Visibility,
3823-
PrivateEndpointType: c.PrivateEndpointType,
3824-
EndpointsFile: c.EndpointsFile,
3825-
UserAgent: fmt.Sprintf("terraform-provider-ibm/%s", version.Version),
3783+
var authenticator core.Authenticator
3784+
var err error
3785+
iamURL := EnvFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, IAMURL)
3786+
if (c.BluemixAPIKey != "") && (c.IAMTrustedProfileID != "" || c.IAMTrustedProfileName != "") {
3787+
if c.IAMTrustedProfileID != "" {
3788+
authenticator, err = core.NewIamAssumeAuthenticatorBuilder().
3789+
SetApiKey(c.BluemixAPIKey).
3790+
SetIAMProfileID(c.IAMTrustedProfileID).
3791+
SetURL(iamURL).
3792+
Build()
3793+
if err != nil {
3794+
log.Fatalf("Error in authenticating using NewIamAssumeAuthenticatorBuilder. Error: %s", err)
3795+
}
3796+
} else {
3797+
authenticator, err = core.NewIamAssumeAuthenticatorBuilder().
3798+
SetApiKey(c.BluemixAPIKey).
3799+
SetIAMProfileName(c.IAMTrustedProfileName).
3800+
SetIAMAccountID(c.Account).
3801+
SetURL(iamURL).
3802+
Build()
3803+
if err != nil {
3804+
log.Fatalf("Error in authenticating using NewIamAssumeAuthenticatorBuilder with trusted profile name. Error: %s", err)
3805+
}
38263806
}
3827-
sess, err := bxsession.New(bmxConfig)
3828-
if err != nil {
3829-
return nil, err
3807+
} else if c.BluemixAPIKey != "" || c.IAMRefreshToken != "" {
3808+
if c.BluemixAPIKey != "" {
3809+
authenticator = &core.IamAuthenticator{
3810+
ApiKey: c.BluemixAPIKey,
3811+
URL: iamURL,
3812+
}
3813+
} else {
3814+
// Construct the IamAuthenticator with the IAM refresh token.
3815+
authenticator = &core.IamAuthenticator{
3816+
RefreshToken: c.IAMRefreshToken,
3817+
ClientId: "bx",
3818+
ClientSecret: "bx",
3819+
URL: iamURL,
3820+
}
38303821
}
3831-
ibmSession.BluemixSession = sess
3832-
}
3833-
3834-
if c.BluemixAPIKey != "" {
3835-
log.Println("Configuring IBM Cloud Session with API key")
3836-
var sess *bxsession.Session
3837-
bmxConfig := &bluemix.Config{
3838-
BluemixAPIKey: c.BluemixAPIKey,
3839-
// Comment out debug mode for v0.12
3840-
Debug: os.Getenv("TF_LOG") != "",
3841-
HTTPTimeout: c.BluemixTimeout,
3842-
Region: c.Region,
3843-
ResourceGroup: c.ResourceGroup,
3844-
RetryDelay: &c.RetryDelay,
3845-
MaxRetries: &c.RetryCount,
3846-
Visibility: c.Visibility,
3847-
PrivateEndpointType: c.PrivateEndpointType,
3848-
EndpointsFile: c.EndpointsFile,
3849-
UserAgent: fmt.Sprintf("terraform-provider-ibm/%s", version.Version),
3850-
IAMTrustedProfileID: c.IAMTrustedProfileID,
3822+
} else if strings.HasPrefix(c.IAMToken, "Bearer") {
3823+
authenticator = &core.BearerTokenAuthenticator{
3824+
BearerToken: c.IAMToken[7:],
38513825
}
3852-
sess, err := bxsession.New(bmxConfig)
3853-
if err != nil {
3854-
return nil, err
3826+
} else {
3827+
authenticator = &core.BearerTokenAuthenticator{
3828+
BearerToken: c.IAMToken,
38553829
}
3856-
ibmSession.BluemixSession = sess
38573830
}
38583831

3832+
var sess *bxsession.Session
3833+
bmxConfig := &bluemix.Config{
3834+
IAMAccessToken: c.IAMToken,
3835+
IAMRefreshToken: c.IAMRefreshToken,
3836+
BluemixAPIKey: c.BluemixAPIKey,
3837+
// Comment out debug mode for v0.12
3838+
Debug: os.Getenv("TF_LOG") != "",
3839+
HTTPTimeout: c.BluemixTimeout,
3840+
Region: c.Region,
3841+
ResourceGroup: c.ResourceGroup,
3842+
RetryDelay: &c.RetryDelay,
3843+
MaxRetries: &c.RetryCount,
3844+
Visibility: c.Visibility,
3845+
PrivateEndpointType: c.PrivateEndpointType,
3846+
EndpointsFile: c.EndpointsFile,
3847+
UserAgent: fmt.Sprintf("terraform-provider-ibm/%s", version.Version),
3848+
Authenticator: authenticator,
3849+
}
3850+
sess, err = bxsession.New(bmxConfig)
3851+
if err != nil {
3852+
return nil, err
3853+
}
3854+
ibmSession.BluemixSession = sess
3855+
38593856
return ibmSession, nil
38603857
}
38613858

3862-
func authenticateAPIKey(sess *bxsession.Session) error {
3859+
/*func authenticateAPIKey(sess *bxsession.Session) error {
38633860
config := sess.Config
38643861
tokenRefresher, err := authentication.NewIAMAuthRepository(config, &rest.Client{
38653862
DefaultHeader: gohttp.Header{
@@ -3885,6 +3882,20 @@ func authenticateAssume(sess *bxsession.Session) error {
38853882
return err
38863883
}
38873884
return tokenRefresher.AuthenticateAssume(config.BluemixAPIKey, config.IAMTrustedProfileID)
3885+
}*/
3886+
3887+
func fetchAuthorizationData(sess *bxsession.Session) error {
3888+
config := sess.Config
3889+
tokenRefresher, err := authentication.NewIAMAuthRepository(config, &rest.Client{
3890+
DefaultHeader: gohttp.Header{
3891+
"User-Agent": []string{http.UserAgent()},
3892+
"X-Original-User-Agent": []string{config.UserAgent},
3893+
},
3894+
})
3895+
if err != nil {
3896+
return err
3897+
}
3898+
return tokenRefresher.FetchAuthorizationData(config.Authenticator)
38883899
}
38893900

38903901
func fetchUserDetails(sess *bxsession.Session, retries int, retryDelay time.Duration) (*UserConfig, error) {
@@ -3904,18 +3915,9 @@ func fetchUserDetails(sess *bxsession.Session, retries int, retryDelay time.Dura
39043915
// TODO validate with key
39053916
if err != nil && !strings.Contains(err.Error(), "key is of invalid type") {
39063917
if retries > 0 {
3907-
if config.BluemixAPIKey != "" && config.IAMTrustedProfileID == "" {
3908-
time.Sleep(retryDelay)
3909-
log.Printf("Retrying authentication for user details %d", retries)
3910-
_ = authenticateAPIKey(sess)
3911-
return fetchUserDetails(sess, retries-1, retryDelay)
3912-
} else if config.BluemixAPIKey != "" && config.IAMTrustedProfileID != "" {
3913-
time.Sleep(retryDelay)
3914-
log.Printf("Retrying authentication for user details %d", retries)
3915-
_ = authenticateAssume(sess)
3916-
return fetchUserDetails(sess, retries-1, retryDelay)
3917-
3918-
}
3918+
time.Sleep(retryDelay)
3919+
log.Printf("Retrying authentication for user details %d", retries)
3920+
_ = fetchAuthorizationData(sess)
39193921
}
39203922
return &user, err
39213923
}

0 commit comments

Comments
 (0)