Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workload identity #335

Merged
merged 10 commits into from
Oct 3, 2023
2 changes: 2 additions & 0 deletions api/v1beta2/ociclusteridentity_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const (
UserPrincipal PrincipalType = "UserPrincipal"
// InstancePrincipal represents a instance principal.
InstancePrincipal PrincipalType = "InstancePrincipal"
// WorkloadPrincipal represents a workload principal.
WorkloadPrincipal PrincipalType = "Workload"
)

// OCIClusterIdentitySpec defines the parameters that are used to create an OCIClusterIdentity.
Expand Down
79 changes: 79 additions & 0 deletions cloud/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ import (
"context"
"crypto/x509"
"fmt"
"io"
"net/http"
"os"
"reflect"
"sigs.k8s.io/controller-runtime/pkg/log"
shyamradhakrishnan marked this conversation as resolved.
Show resolved Hide resolved
"time"

"github.com/go-logr/logr"
infrastructurev1beta2 "github.com/oracle/cluster-api-provider-oci/api/v1beta2"
Expand All @@ -43,6 +48,14 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

const (
instanceMetadataRegionInfoURLV2 = "http://169.254.169.254/opc/v2/instance/regionInfo/regionIdentifier"
)

var (
currentRegion *string
)

// GetClusterIdentityFromRef returns the OCIClusterIdentity referenced by the OCICluster.
func GetClusterIdentityFromRef(ctx context.Context, c client.Client, ociClusterNamespace string, ref *corev1.ObjectReference) (*infrastructurev1beta2.OCIClusterIdentity, error) {
identity := &infrastructurev1beta2.OCIClusterIdentity{}
Expand Down Expand Up @@ -97,6 +110,7 @@ func getOCIClientCertPool(ctx context.Context, c client.Client, namespace string

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

if err != nil {
return nil, err
}
return clientProvider, nil
} else if identity.Spec.Type == infrastructurev1beta2.WorkloadPrincipal {
_, containsVersion := os.LookupEnv(auth.ResourcePrincipalVersionEnvVar)
if !containsVersion {
os.Setenv(auth.ResourcePrincipalVersionEnvVar, auth.ResourcePrincipalVersion1_1)
shyamradhakrishnan marked this conversation as resolved.
Show resolved Hide resolved
}
_, containsRegion := os.LookupEnv(auth.ResourcePrincipalRegionEnvVar)
if !containsRegion {
// initialize the current region from region metadata
if currentRegion == nil {
regionByte, err := getRegionInfoFromInstanceMetadataServiceProd()
if err != nil {
return nil, err
}
currentRegion = common.String(string(regionByte))
}
logger.Info(fmt.Sprintf("Looked up region %s from instance metadata", *currentRegion))
os.Setenv(auth.ResourcePrincipalRegionEnvVar, *currentRegion)
}

provider, err := auth.OkeWorkloadIdentityConfigurationProvider()
if err != nil {
return nil, err
}
pool, err := getOCIClientCertPool(ctx, c, namespace, clientOverrides)
if err != nil {
return nil, err
}
clientProvider, err := scope.NewClientProvider(scope.ClientProviderParams{
CertOverride: pool,
OciAuthConfigProvider: provider,
ClientOverrides: clientOverrides})

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -406,6 +456,35 @@ func DeleteOrphanedMachinePoolMachines(ctx context.Context, params MachineParams

return nil
}
func getRegionInfoFromInstanceMetadataServiceProd() ([]byte, error) {
request, err := http.NewRequest(http.MethodGet, instanceMetadataRegionInfoURLV2, nil)
request.Header.Add("Authorization", "Bearer Oracle")

client := &http.Client{
Timeout: time.Second * 10,
}
resp, err := client.Do(request)
if err != nil {
return nil, errors.Wrap(err, "failed to call instance metadata service")
}

statusCode := resp.StatusCode

defer resp.Body.Close()

content, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "failed to get region information from response body")
}

if statusCode != http.StatusOK {
err = fmt.Errorf("HTTP Get failed: URL: %s, Status: %s, Message: %s",
instanceMetadataRegionInfoURLV2, resp.Status, string(content))
return nil, err
}

return content, nil
}

// MachineParams specifies the params required to create or delete machinepool machines.
// Infra machine pool specifed below refers to OCIManagedMachinePool/OCIMachinePool/OCIVirtualMachinePool
Expand Down
19 changes: 18 additions & 1 deletion docs/src/gs/multi-tenancy.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,22 @@ spec:
allowedNamespaces: {}
```

## Cluster Identity using Workload Identity

Cluster Identity supports [Workload][workload] access to OCI resources also knows as Workload Identity. The example
`OCIClusterIdentity` spec shown below uses Workload Identity.

```yaml
---
kind: OCIClusterIdentity
metadata:
name: cluster-identity
namespace: default
spec:
type: Workload
allowedNamespaces: {}
```

[iam-user]: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#Required_Keys_and_OCIDs
[instance-principals]: https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm
[instance-principals]: https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm
[workload]: https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contenggrantingworkloadaccesstoresources.htm