Skip to content

Commit 85b13cd

Browse files
simonlordprydie
authored andcommitted
Support authentication via instance principals (#155) (#181)
1 parent cdb5038 commit 85b13cd

File tree

5 files changed

+95
-11
lines changed

5 files changed

+95
-11
lines changed

manifests/cloud-provider-example.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ auth:
1010
passphrase: supersecretpassword
1111
fingerprint: 8c:bf:17:7b:5f:e0:7d:13:75:11:d6:39:0d:e2:84:74
1212

13+
# Omit all of the above options then set useInstancePrincipals to true if you
14+
# want to use Instance Principals API access
15+
# (https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Tasks/callingservicesfrominstances.htm).
16+
# Ensure you have setup the following OCI policies and your kubernetes nodes are running within them
17+
# allow dynamic-group [your dynamic group name] to read instance-family in compartment [your compartment name]
18+
# allow dynamic-group [your dynamic group name] to use virtual-network-family in compartment [your compartment name]
19+
# allow dynamic-group [your dynamic group name] to manage load-balancers in compartment [your compartment name]
20+
useInstancePrincipals: false
21+
1322
# compartment configures Compartment within which the cluster resides.
1423
compartment: ocid1.compartment.oc1..aaaaaaaa3um2atybwhder4qttfhgon4j3hcxgmsvnyvx4flfjyewkkwfzwnq
1524

pkg/oci/ccm.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"github.com/golang/glog"
2727
"github.com/oracle/oci-go-sdk/common"
28+
"github.com/oracle/oci-go-sdk/common/auth"
2829
"github.com/pkg/errors"
2930

3031
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -68,14 +69,11 @@ var _ cloudprovider.Interface = &CloudProvider{}
6869

6970
// NewCloudProvider creates a new oci.CloudProvider.
7071
func NewCloudProvider(config *Config) (cloudprovider.Interface, error) {
71-
c, err := client.New(common.NewRawConfigurationProvider(
72-
config.Auth.TenancyID,
73-
config.Auth.UserID,
74-
config.Auth.Region,
75-
config.Auth.Fingerprint,
76-
config.Auth.PrivateKey,
77-
&config.Auth.Passphrase,
78-
))
72+
cp, err := buildConfigurationProvider(config)
73+
if err != nil {
74+
return nil, err
75+
}
76+
c, err := client.New(cp)
7977
if err != nil {
8078
return nil, err
8179
}
@@ -199,3 +197,24 @@ func (cp *CloudProvider) ScrubDNS(nameservers, searches []string) (nsOut, srchOu
199197
func (cp *CloudProvider) HasClusterID() bool {
200198
return true
201199
}
200+
201+
func buildConfigurationProvider(config *Config) (common.ConfigurationProvider, error) {
202+
if config.Auth.UseInstancePrincipals {
203+
glog.V(2).Info("Using instance principals configuration provider")
204+
cp, err := auth.InstancePrincipalConfigurationProvider()
205+
if err != nil {
206+
return nil, errors.Wrap(err, "InstancePrincipalConfigurationProvider")
207+
}
208+
return cp, nil
209+
}
210+
glog.V(2).Info("Using raw configuration provider")
211+
cp := common.NewRawConfigurationProvider(
212+
config.Auth.TenancyID,
213+
config.Auth.UserID,
214+
config.Auth.Region,
215+
config.Auth.Fingerprint,
216+
config.Auth.PrivateKey,
217+
&config.Auth.Passphrase,
218+
)
219+
return cp, nil
220+
}

pkg/oci/config.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import (
2626
// AuthConfig holds the configuration required for communicating with the OCI
2727
// API.
2828
type AuthConfig struct {
29-
Region string `yaml:"region"`
30-
TenancyID string `yaml:"tenancy"`
29+
UseInstancePrincipals bool `yaml:"useInstancePrincipals"`
30+
Region string `yaml:"region"`
31+
TenancyID string `yaml:"tenancy"`
3132
// CompartmentID is DEPRECIATED and should be set on the top level Config
3233
// struct.
3334
CompartmentID string `yaml:"compartment"`

pkg/oci/config_validate.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@ func validateAuthConfig(c *AuthConfig, fldPath *field.Path) field.ErrorList {
2424
if c == nil {
2525
return append(allErrs, field.Required(fldPath, ""))
2626
}
27+
if c.UseInstancePrincipals {
28+
if c.Region != "" {
29+
allErrs = append(allErrs, field.Forbidden(fldPath.Child("region"), "cannot be used when useInstancePrincipals is enabled"))
30+
}
31+
if c.TenancyID != "" {
32+
allErrs = append(allErrs, field.Forbidden(fldPath.Child("tenancy"), "cannot be used when useInstancePrincipals is enabled"))
33+
}
34+
if c.UserID != "" {
35+
allErrs = append(allErrs, field.Forbidden(fldPath.Child("user"), "cannot be used when useInstancePrincipals is enabled"))
36+
}
37+
if c.PrivateKey != "" {
38+
allErrs = append(allErrs, field.Forbidden(fldPath.Child("key"), "cannot be used when useInstancePrincipals is enabled"))
39+
}
40+
if c.Fingerprint != "" {
41+
allErrs = append(allErrs, field.Forbidden(fldPath.Child("fingerprint"), "cannot be used when useInstancePrincipals is enabled"))
42+
}
43+
44+
return allErrs
45+
}
2746
if c.Region == "" {
2847
allErrs = append(allErrs, field.Required(fldPath.Child("region"), ""))
2948
}

pkg/oci/config_validate_test.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,42 @@ func TestValidateConfig(t *testing.T) {
4444
},
4545
},
4646
errs: field.ErrorList{},
47+
},
48+
{
49+
name: "valid with instance principals enabled",
50+
in: &Config{
51+
Auth: AuthConfig{
52+
UseInstancePrincipals: true,
53+
},
54+
LoadBalancer: LoadBalancerConfig{
55+
Subnet1: "ocid1.tenancy.oc1..aaaaaaaatyn7scrtwtqedvgrxgr2xunzeo6uanvyhzxqblctwkrpisvke4kq",
56+
Subnet2: "ocid1.subnet.oc1.phx.aaaaaaaahuxrgvs65iwdz7ekwgg3l5gyah7ww5klkwjcso74u3e4i64hvtvq",
57+
},
58+
},
59+
errs: field.ErrorList{},
60+
}, {
61+
name: "mixing instance principals with other auth flags",
62+
in: &Config{
63+
Auth: AuthConfig{
64+
UseInstancePrincipals: true,
65+
Region: "us-phoenix-1",
66+
TenancyID: "ocid1.tenancy.oc1..aaaaaaaatyn7scrtwtqedvgrxgr2xunzeo6uanvyhzxqblctwkrpisvke4kq",
67+
UserID: "ocid1.user.oc1..aaaaaaaai77mql2xerv7cn6wu3nhxang3y4jk56vo5bn5l5lysl34avnui3q",
68+
PrivateKey: "-----BEGIN RSA PRIVATE KEY----- (etc)",
69+
Fingerprint: "8c:bf:17:7b:5f:e0:7d:13:75:11:d6:39:0d:e2:84:74",
70+
},
71+
LoadBalancer: LoadBalancerConfig{
72+
Subnet1: "ocid1.tenancy.oc1..aaaaaaaatyn7scrtwtqedvgrxgr2xunzeo6uanvyhzxqblctwkrpisvke4kq",
73+
Subnet2: "ocid1.subnet.oc1.phx.aaaaaaaahuxrgvs65iwdz7ekwgg3l5gyah7ww5klkwjcso74u3e4i64hvtvq",
74+
},
75+
},
76+
errs: field.ErrorList{
77+
&field.Error{Type: field.ErrorTypeForbidden, Field: "auth.region", Detail: "cannot be used when useInstancePrincipals is enabled", BadValue: ""},
78+
&field.Error{Type: field.ErrorTypeForbidden, Field: "auth.tenancy", Detail: "cannot be used when useInstancePrincipals is enabled", BadValue: ""},
79+
&field.Error{Type: field.ErrorTypeForbidden, Field: "auth.user", Detail: "cannot be used when useInstancePrincipals is enabled", BadValue: ""},
80+
&field.Error{Type: field.ErrorTypeForbidden, Field: "auth.key", Detail: "cannot be used when useInstancePrincipals is enabled", BadValue: ""},
81+
&field.Error{Type: field.ErrorTypeForbidden, Field: "auth.fingerprint", Detail: "cannot be used when useInstancePrincipals is enabled", BadValue: ""},
82+
},
4783
}, {
4884
name: "valid_with_non_default_security_list_management_mode",
4985
in: &Config{
@@ -237,7 +273,7 @@ func TestValidateConfig(t *testing.T) {
237273
tt.in.Complete()
238274
result := ValidateConfig(tt.in)
239275
if !reflect.DeepEqual(result, tt.errs) {
240-
t.Errorf("ValidateConfig(%#v)\n=> %q \nExpected: %q", tt.in, result, tt.errs)
276+
t.Errorf("ValidateConfig(%#v)\n=> %q \nExpected: %q", tt.in, result, tt.errs)
241277
}
242278
})
243279
}

0 commit comments

Comments
 (0)