Skip to content

Commit

Permalink
implement session token support for Azure federated credentials (#301)
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Liu <[email protected]>
  • Loading branch information
shenmo3 authored Aug 24, 2023
1 parent a52bffd commit d0b4c3c
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 62 deletions.
1 change: 1 addition & 0 deletions apis/crd/v1alpha1/cloudprovideraccount_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type AzureAccountCredential struct {
ClientID string `json:"clientId,omitempty"`
TenantID string `json:"tenantId,omitempty"`
ClientKey string `json:"clientKey,omitempty"`
SessionToken string `json:"sessionToken,omitempty"`
}

// CloudProviderAccountStatus defines the observed state of CloudProviderAccount.
Expand Down
7 changes: 6 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,14 @@ EOF
To get the base64 encoded json string for credential, run:

```bash
echo '{"subscriptionId": "YOUR_AZURE_SUBSCRIPTION_ID", "clientId": "YOUR_AZURE_CLIENT_ID", "tenantId": "YOUR_AZURE_TENANT_ID", "clientKey": "YOUR_AZURE_CLIENT_KEY"}' | openssl base64 | tr -d '\n'
echo '{"subscriptionId": "YOUR_AZURE_SUBSCRIPTION_ID", "clientId": "YOUR_AZURE_CLIENT_ID", "tenantId": "YOUR_AZURE_TENANT_ID", "clientKey": "YOUR_AZURE_CLIENT_KEY", "sessionToken": "YOUR_AZURE_SESSION_TOKEN"}' | openssl base64 | tr -d '\n'
```

Note: either `clientKey` or `sessionToken` must be specified. `clientKey` is
used for credentials, and `sessionToken` is used for Azure federated credential
on managed identities. You can read more about Azure federated credential in
[federated identity credential documentation](https://azure.github.io/azure-workload-identity/docs/topics/federated-identity-credential.html).

```bash
cat <<EOF | kubectl apply -f -
apiVersion: v1
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ go 1.21

require (
antrea.io/antrea v1.12.0
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.6.0
Expand All @@ -31,9 +31,9 @@ require (
)

require (
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
github.com/beorn7/perks v1.0.1 // indirect
Expand All @@ -54,7 +54,7 @@ require (
github.com/go-openapi/swag v0.19.14 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/cel-go v0.12.6 // indirect
Expand All @@ -76,7 +76,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.15.1 // indirect
Expand Down
27 changes: 14 additions & 13 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0 h1:sVPhtT2qjO86rTUaWMr4WoES4TkjGnzcioXcnHV9s5k=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 h1:/Di3vB4sNeQ+7A8efjUVENvyB945Wruvstucqp7ZArg=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0/go.mod h1:gM3K25LQlsET3QR+4V74zxCsFAy0r6xMNN9n80SZn+4=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ=
Expand All @@ -58,8 +58,8 @@ github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
Expand Down Expand Up @@ -110,7 +110,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
Expand Down Expand Up @@ -169,8 +169,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
Expand Down Expand Up @@ -326,8 +326,8 @@ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down Expand Up @@ -593,6 +593,7 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
34 changes: 19 additions & 15 deletions pkg/apiserver/webhook/cloudprovideraccount_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,18 @@ import (
const MinPollInterval = 30

var (
errorMsgSecretNotConfigured = "unable to get secret"
errorMsgMinPollInterval = "pollIntervalInSeconds should be >= 30. If not specified, defaults to 60"
errorMsgMissingCredential = "must specify either credentials or role arn, cannot both be empty"
errorMsgMissingRegion = "region cannot be blank or empty"
errorMsgInvalidRegion = "not in supported regions"
errorMsgJsonUnmarshalFail = "unable to unmarshal the json"
errorMsgMissingClientDetails = "client id and client key cannot be blank or empty"
errorMsgMissingTenantID = "tenant id cannot be blank or empty"
errorMsgMissingSubscritionID = "subscription id cannot be blank or empty"
errorMsgInvalidRequest = "invalid admission webhook request"
errorMsgDecodeFail = "unable to decode the secret"
errorMsgSecretNotConfigured = "unable to get secret"
errorMsgMinPollInterval = "pollIntervalInSeconds should be >= 30. If not specified, defaults to 60"
errorMsgMissingAwsCredential = "must specify either credentials or role arn, both cannot be empty"
errorMsgMissingRegion = "region cannot be blank or empty"
errorMsgInvalidRegion = "not in supported regions"
errorMsgJsonUnmarshalFail = "unable to unmarshal the json"
errorMsgMissingClientID = "client id cannot be blank or empty"
errorMsgMissingAzureCredential = "must specify either client key or session token, both cannot be empty"
errorMsgMissingTenantID = "tenant id cannot be blank or empty"
errorMsgMissingSubscriptionID = "subscription id cannot be blank or empty"
errorMsgInvalidRequest = "invalid admission webhook request"
errorMsgDecodeFail = "unable to decode the secret"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -244,7 +245,7 @@ func (v *CPAValidator) validateAWSAccount(account *crdv1alpha1.CloudProviderAcco
v.Log.Info("Role ARN configured will be used for cloud-account access")
} else if len(strings.TrimSpace(awsCredential.AccessKeyID)) == 0 ||
len(strings.TrimSpace(awsCredential.AccessKeySecret)) == 0 {
return fmt.Errorf(errorMsgMissingCredential)
return fmt.Errorf(errorMsgMissingAwsCredential)
}

if len(awsConfig.Region) == 0 || len(strings.TrimSpace(awsConfig.Region[0])) == 0 {
Expand Down Expand Up @@ -296,15 +297,18 @@ func (v *CPAValidator) validateAzureAccount(account *crdv1alpha1.CloudProviderAc

// validate subscription ID
if len(strings.TrimSpace(azureCredential.SubscriptionID)) == 0 {
return fmt.Errorf(errorMsgMissingSubscritionID)
return fmt.Errorf(errorMsgMissingSubscriptionID)
}
// validate tenant ID
if len(strings.TrimSpace(azureCredential.TenantID)) == 0 {
return fmt.Errorf(errorMsgMissingTenantID)
}
// validate credentials
if len(strings.TrimSpace(azureCredential.ClientID)) == 0 || len(strings.TrimSpace(azureCredential.ClientKey)) == 0 {
return fmt.Errorf(errorMsgMissingClientDetails)
if len(strings.TrimSpace(azureCredential.ClientID)) == 0 {
return fmt.Errorf(errorMsgMissingClientID)
}
if len(strings.TrimSpace(azureCredential.ClientKey)) == 0 && len(strings.TrimSpace(azureCredential.SessionToken)) == 0 {
return fmt.Errorf(errorMsgMissingAzureCredential)
}

// validate region
Expand Down
89 changes: 85 additions & 4 deletions pkg/apiserver/webhook/cloudprovideraccount_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ var _ = Describe("CloudProviderAccountWebhook", func() {
response := validator.Handle(context.Background(), accountReq)
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response)))
Expect(response.AdmissionResponse.Allowed).To(BeFalse())
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingCredential))
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingAwsCredential))
})
It("Validate missing region in AWS", func() {
err = fakeClient.Create(context.Background(), s1)
Expand Down Expand Up @@ -724,7 +724,7 @@ var _ = Describe("CloudProviderAccountWebhook", func() {
Expect(response.AdmissionResponse.Allowed).To(BeFalse())
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgSecretNotConfigured))
})
It("Validate an Azure Account add", func() {
It("Validate an Azure Account add with credential", func() {
cred := `{"subscriptionId": "SubID","clientId": "ClientID","tenantId": "TenantID", "clientKey": "ClientKey"}`
s1 := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -764,6 +764,46 @@ var _ = Describe("CloudProviderAccountWebhook", func() {
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response)))
Expect(response.AdmissionResponse.Allowed).To(BeTrue())
})
It("Validate an Azure Account add with session token", func() {
cred := `{"subscriptionId": "SubID","clientId": "ClientID","tenantId": "TenantID", "sessionToken": "sessionToken"}`
s1 := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: testSecretNamespacedName.Name,
Namespace: testSecretNamespacedName.Namespace,
},
Data: map[string][]byte{
credentials: []byte(cred),
},
}
err = fakeClient.Create(context.Background(), s1)
Expect(err).Should(BeNil())

encodedAccount, _ = json.Marshal(azureAccount)
accountReq = admission.Request{
AdmissionRequest: v1.AdmissionRequest{
Kind: metav1.GroupVersionKind{
Group: "",
Version: "v1alpha1",
Kind: "CloudProviderAccount",
},
Resource: metav1.GroupVersionResource{
Group: "",
Version: "v1alpha1",
Resource: "CloudProviderAccounts",
},
Name: testAccountNamespacedName.Name,
Namespace: testAccountNamespacedName.Namespace,
Operation: v1.Create,
Object: runtime.RawExtension{
Raw: encodedAccount,
},
},
}

response := validator.Handle(context.Background(), accountReq)
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response)))
Expect(response.AdmissionResponse.Allowed).To(BeTrue())
})
It("Validate Azure secret unmarshall error", func() {
s1 := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -843,7 +883,7 @@ var _ = Describe("CloudProviderAccountWebhook", func() {
response := validator.Handle(context.Background(), accountReq)
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response)))
Expect(response.AdmissionResponse.Allowed).To(BeFalse())
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingSubscritionID))
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingSubscriptionID))
})
It("Validate missing Azure clientID", func() {
cred := `{"subscriptionId": "SubID","tenantId": "TenantID", "clientKey": "ClientKey"}`
Expand Down Expand Up @@ -884,7 +924,7 @@ var _ = Describe("CloudProviderAccountWebhook", func() {
response := validator.Handle(context.Background(), accountReq)
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response)))
Expect(response.AdmissionResponse.Allowed).To(BeFalse())
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingClientDetails))
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingClientID))
})
It("Validate missing Azure TenantID", func() {
cred := `{"subscriptionId": "SubID", "clientId": "ClientID", "clientKey": "ClientKey"}`
Expand Down Expand Up @@ -927,6 +967,47 @@ var _ = Describe("CloudProviderAccountWebhook", func() {
Expect(response.AdmissionResponse.Allowed).To(BeFalse())
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingTenantID))
})
It("Validate missing Azure credential", func() {
cred := `{"subscriptionId": "SubID", "clientId": "ClientID", "tenantId": "TenantID"}`
s1 := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: testSecretNamespacedName.Name,
Namespace: testSecretNamespacedName.Namespace,
},
Data: map[string][]byte{
credentials: []byte(cred),
},
}
err = fakeClient.Create(context.Background(), s1)
Expect(err).Should(BeNil())

encodedAccount, _ = json.Marshal(azureAccount)
accountReq = admission.Request{
AdmissionRequest: v1.AdmissionRequest{
Kind: metav1.GroupVersionKind{
Group: "",
Version: "v1alpha1",
Kind: "CloudProviderAccount",
},
Resource: metav1.GroupVersionResource{
Group: "",
Version: "v1alpha1",
Resource: "CloudProviderAccounts",
},
Name: testAccountNamespacedName.Name,
Namespace: testAccountNamespacedName.Namespace,
Operation: v1.Create,
Object: runtime.RawExtension{
Raw: encodedAccount,
},
},
}

response := validator.Handle(context.Background(), accountReq)
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response)))
Expect(response.AdmissionResponse.Allowed).To(BeFalse())
Expect(response.AdmissionResponse.String()).Should(ContainSubstring(errorMsgMissingAzureCredential))
})
It("Validate webhook update", func() {
err = fakeClient.Create(context.Background(), s1)
Expect(err).Should(BeNil())
Expand Down
2 changes: 1 addition & 1 deletion pkg/cloudprovider/plugins/aws/aws_account_mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func extractSecret(c client.Client, s *crdv1alpha1.SecretReference) (*crdv1alpha
return cred, fmt.Errorf("%v, error unmarshalling credentials: %v/%v", util.ErrorMsgSecretReference, s.Namespace, s.Name)
}

if (cred.AccessKeyID == "" || cred.AccessKeySecret == "") && cred.RoleArn == "" {
if (strings.TrimSpace(cred.AccessKeyID) == "" || strings.TrimSpace(cred.AccessKeySecret) == "") && strings.TrimSpace(cred.RoleArn) == "" {
return cred, fmt.Errorf("%v, Secret credentials cannot be empty: %v/%v", util.ErrorMsgSecretReference, s.Namespace, s.Name)
}

Expand Down
Loading

0 comments on commit d0b4c3c

Please sign in to comment.