Skip to content

Commit 241cf91

Browse files
Workload identity (#335)
* Add support for workload identity
1 parent bf1c037 commit 241cf91

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

api/v1beta2/ociclusteridentity_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ const (
2929
UserPrincipal PrincipalType = "UserPrincipal"
3030
// InstancePrincipal represents a instance principal.
3131
InstancePrincipal PrincipalType = "InstancePrincipal"
32+
// WorkloadPrincipal represents a workload principal.
33+
WorkloadPrincipal PrincipalType = "Workload"
3234
)
3335

3436
// OCIClusterIdentitySpec defines the parameters that are used to create an OCIClusterIdentity.

cloud/util/util.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import (
2020
"context"
2121
"crypto/x509"
2222
"fmt"
23+
"io"
24+
"net/http"
25+
"os"
2326
"reflect"
27+
"time"
2428

2529
"github.com/go-logr/logr"
2630
infrastructurev1beta2 "github.com/oracle/cluster-api-provider-oci/api/v1beta2"
@@ -41,6 +45,15 @@ import (
4145
"sigs.k8s.io/cluster-api/util/patch"
4246
"sigs.k8s.io/controller-runtime/pkg/client"
4347
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
48+
"sigs.k8s.io/controller-runtime/pkg/log"
49+
)
50+
51+
const (
52+
instanceMetadataRegionInfoURLV2 = "http://169.254.169.254/opc/v2/instance/regionInfo/regionIdentifier"
53+
)
54+
55+
var (
56+
currentRegion *string
4457
)
4558

4659
// GetClusterIdentityFromRef returns the OCIClusterIdentity referenced by the OCICluster.
@@ -97,6 +110,7 @@ func getOCIClientCertPool(ctx context.Context, c client.Client, namespace string
97110

98111
// GetOrBuildClientFromIdentity creates ClientProvider from OCIClusterIdentity object
99112
func GetOrBuildClientFromIdentity(ctx context.Context, c client.Client, identity *infrastructurev1beta2.OCIClusterIdentity, defaultRegion string, clientOverrides *infrastructurev1beta2.ClientOverrides, namespace string) (*scope.ClientProvider, error) {
113+
logger := log.FromContext(ctx)
100114
if identity.Spec.Type == infrastructurev1beta2.UserPrincipal {
101115
secretRef := identity.Spec.PrincipalSecret
102116
key := types.NamespacedName{
@@ -155,6 +169,42 @@ func GetOrBuildClientFromIdentity(ctx context.Context, c client.Client, identity
155169
OciAuthConfigProvider: provider,
156170
ClientOverrides: clientOverrides})
157171

172+
if err != nil {
173+
return nil, err
174+
}
175+
return clientProvider, nil
176+
} else if identity.Spec.Type == infrastructurev1beta2.WorkloadPrincipal {
177+
_, containsVersion := os.LookupEnv(auth.ResourcePrincipalVersionEnvVar)
178+
if !containsVersion {
179+
os.Setenv(auth.ResourcePrincipalVersionEnvVar, auth.ResourcePrincipalVersion2_2)
180+
}
181+
_, containsRegion := os.LookupEnv(auth.ResourcePrincipalRegionEnvVar)
182+
if !containsRegion {
183+
// initialize the current region from region metadata
184+
if currentRegion == nil {
185+
regionByte, err := getRegionInfoFromInstanceMetadataServiceProd()
186+
if err != nil {
187+
return nil, err
188+
}
189+
currentRegion = common.String(string(regionByte))
190+
}
191+
logger.Info(fmt.Sprintf("Looked up region %s from instance metadata", *currentRegion))
192+
os.Setenv(auth.ResourcePrincipalRegionEnvVar, *currentRegion)
193+
}
194+
195+
provider, err := auth.OkeWorkloadIdentityConfigurationProvider()
196+
if err != nil {
197+
return nil, err
198+
}
199+
pool, err := getOCIClientCertPool(ctx, c, namespace, clientOverrides)
200+
if err != nil {
201+
return nil, err
202+
}
203+
clientProvider, err := scope.NewClientProvider(scope.ClientProviderParams{
204+
CertOverride: pool,
205+
OciAuthConfigProvider: provider,
206+
ClientOverrides: clientOverrides})
207+
158208
if err != nil {
159209
return nil, err
160210
}
@@ -406,6 +456,35 @@ func DeleteOrphanedMachinePoolMachines(ctx context.Context, params MachineParams
406456

407457
return nil
408458
}
459+
func getRegionInfoFromInstanceMetadataServiceProd() ([]byte, error) {
460+
request, err := http.NewRequest(http.MethodGet, instanceMetadataRegionInfoURLV2, nil)
461+
request.Header.Add("Authorization", "Bearer Oracle")
462+
463+
client := &http.Client{
464+
Timeout: time.Second * 10,
465+
}
466+
resp, err := client.Do(request)
467+
if err != nil {
468+
return nil, errors.Wrap(err, "failed to call instance metadata service")
469+
}
470+
471+
statusCode := resp.StatusCode
472+
473+
defer resp.Body.Close()
474+
475+
content, err := io.ReadAll(resp.Body)
476+
if err != nil {
477+
return nil, errors.Wrap(err, "failed to get region information from response body")
478+
}
479+
480+
if statusCode != http.StatusOK {
481+
err = fmt.Errorf("HTTP Get failed: URL: %s, Status: %s, Message: %s",
482+
instanceMetadataRegionInfoURLV2, resp.Status, string(content))
483+
return nil, err
484+
}
485+
486+
return content, nil
487+
}
409488

410489
// MachineParams specifies the params required to create or delete machinepool machines.
411490
// Infra machine pool specifed below refers to OCIManagedMachinePool/OCIMachinePool/OCIVirtualMachinePool

docs/src/gs/multi-tenancy.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,22 @@ spec:
8383
allowedNamespaces: {}
8484
```
8585

86+
## Cluster Identity using Workload Identity
87+
88+
Cluster Identity supports [Workload][workload] access to OCI resources also knows as Workload Identity. The example
89+
`OCIClusterIdentity` spec shown below uses Workload Identity.
90+
91+
```yaml
92+
---
93+
kind: OCIClusterIdentity
94+
metadata:
95+
name: cluster-identity
96+
namespace: default
97+
spec:
98+
type: Workload
99+
allowedNamespaces: {}
100+
```
101+
86102
[iam-user]: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#Required_Keys_and_OCIDs
87-
[instance-principals]: https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm
103+
[instance-principals]: https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm
104+
[workload]: https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contenggrantingworkloadaccesstoresources.htm

0 commit comments

Comments
 (0)