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

Support workload identity by enabling 'OIDCTokenFile' as credentials source in providerConfig #402

Merged
merged 8 commits into from
Mar 15, 2023

Conversation

asajoshi
Copy link
Contributor

@asajoshi asajoshi commented Mar 3, 2023

Description of the changes

Goal -

To enable OIDCTokenFile as providerConfig credential source option.
By doing this, provider can perform CRUD operations on resources without passing any secrets in the providerconfig.

This is related to #94

ProviderConfig example-

apiVersion: azure.upbound.io/v1beta1
kind: ProviderConfig
metadata:
    name: upbound-provider-azure-config-umi
spec:
    credentials:
      source: OIDCTokenFile
    clientID: ""   # The managed identity id that your provider wants to assume to manage resources. 
    subscriptionID: "" 
    tenantID: "" 
    oidcTokenFilePath: "/tmp/oidc_token". # Optional field , Defaults to : /var/run/secrets/azure/tokens/azure-identity-token

Dependancy

This PR holds AUTHENTICATION.md. To document the changes suggested in the current PR, we need to make changes in the AUTHENTICATION.md file.

Purpose

Currently, ProviderConfig only supports secret / managed identities as sources of credentials to authenticate the provider to azure. However, terraform azurerm v0.41 also accepts oidc_token_file_path when use_oidc is enabled. If we want to enable authentication using service principle and OpenId connect, the changes in this commit are the simplest way to expose the underlying terraform functionality to do so.

Prerequisites to test the functionality-

  1. Workload identity should be enabled on the AKS cluster where provider-azure is running.
  2. The provider-azure pod and corresponding service account must be properly labelled to aquire the projected-volume azure-identity-token. This can be verified by execing into the pod and checking path /var/run/secrets/azure/tokens where azure-identity-token holds a oidc token.

Fixes #94

I have:

  • Run make reviewable test to ensure this PR is ready for review.
  • Run make local-deploy
  • Created a providerConfig from the example above.
  • Created a sample resourceGroup

How has this code been tested

Install custom azure provider

  1. Install crossplane v1.11 and install azure custom provider , in this step I have already created and pushed a private pkg xpkg.upbound.io/asajoshi/my-repo:v0.30.0 from this PR , you should build it yourself to test it.
$ kubectl apply -f - <<EOF
apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
  labels:
    app: upbound-provider-azure
  name: upbound-provider-azure
spec:
  args:
    - --debug

---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  labels:
    azure.workload.identity/use: "true"
  name: upbound-provider-azure
spec:
  package: xpkg.upbound.io/asajoshi/my-repo:v0.30.0
EOF

# check if pkg is installed and healthy.
$ kubectl get pkg 

  1. We want to create resources in an azure subscription using our crossplane provider-azure. For this to work, we need to create a user managed identity(umi) in that subscription. In this umi, we need to configure an identity from your AKS cluster's OIDC server to get tokens as the umi to access azure AD protected services. This is configured in Federated Credentials tab under umi. we also need to associate a Contributor role to be able to create/update/delete resources.
1. Create a resource group 
$ az group create -l westeurope -n test-rg 
2. Create UMI using azure CLI
$ az identity create --name test-umi --resource-group test-rg 
3. Create Federated credentials
$ az identity federated-credential create --name crossplane-provider-azure --identity-name test-umi --resource-group test-rg --issuer <MyAKS_Cluster_oidc_issuer> --subject <system:serviceaccount:crossplane-system:upbound_provider_azure-service_azzount_name> --audiences api://AzureADTokenExchange
4. Create azure role assignment
$ az role assignment create --assignee-object-id <object_id_of_test_umi> --role Contributor --scope /subscriptions/<subscription_id>

  1. Create providerconfig for authenticating with
# Make sure to change placeholders in the following yaml

$ kubectl apply -f - <<EOF
apiVersion: azure.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: upbound-provider-azure-config-umi
spec:
  credentials:
    source: OIDCTokenFile
  clientID: <client_id_of_test_umi>   # test_umi created in earlier step 
  subscriptionID: <az_subscription_id> 
  tenantID: <tenant_id>
EOF
  1. Edit service account mapped to the provider pod
$ kubectl edit sa $(k get sa -n crossplane-system| grep upbound-provider-azure | awk '{print $1}') -n crossplane-system

# Add the following label to metadata.
metadata:
  labels:
     azure.workload.identity/use: "true"

  1. Edit provider deployment
$ kubectl edit deployment $(k get sa -n crossplane-system| grep upbound-provider-azure | awk '{print $1}') -n crossplane-system 
# Add the following label to deployment template
spec:
    template:
       metadata:
          labels:
            azure.workload.identity/use: "true"
  1. Ensure that the provider pod has azure-identity-token mounted at path /var/run/secrets/azure/tokens/azure-identity-token. Make sure that workload identity is enabled on your AKS cluster.
  2. Create a sample resource group to verify everything works!
$ kubectl apply -f - <<EOF
apiVersion: azure.upbound.io/v1beta1
kind: ResourceGroup
metadata:
  name: ucp-test-group
spec:
  forProvider:
    location: "West Europe"
  providerConfigRef:
    name: upbound-provider-azure-config-umi
EOF

More testing scenarios verified-

  1. TenantID , ClientID and subscription ID are all required , error must be thrown if either of them is missing , that's how it works in terraform azurerm provider v0.41
  2. When providerConfig credential source is set to OIDCTokenFile, if the workload identity is enabled on the pod, the provider should pick up the token from default OidcTokenFilePath : /var/run/secrets/azure/tokens/azure-identity-token.
  3. This path can be modified by passing the variable OidcTokenFilePath, meaning this variable should be optional with a default value set to /var/run/secrets/azure/tokens/azure-identity-token
  4. If the path is non-existent, an error is shown in the resource event logs. This is handled by underlying terraform.
  5. When all the values are correctly passed, crossplane provider pod should be able to automatically create resources without using any secrets in providerconfig. This oidc token in the file should be able to suffice that.
  6. If wrong values are provided for TenantID , ClientID and subscription ID, the provider will either show permission issues or authentication problems.

@asajoshi asajoshi requested a review from sergenyalcin as a code owner March 3, 2023 09:10
@Upbound-CLA
Copy link

Upbound-CLA commented Mar 3, 2023

CLA assistant check
All committers have signed the CLA.

@asajoshi asajoshi changed the title OIDC token file Support workload identity by enabling 'OIDCTokenFile' as credentials source in providerConfig Mar 3, 2023
@turkenf
Copy link
Collaborator

turkenf commented Mar 14, 2023

Required status checks have been changed, could you please rebase this PR?

@asajoshi asajoshi requested a review from ulucinar as a code owner March 14, 2023 12:51
@asajoshi asajoshi closed this Mar 14, 2023
@asajoshi asajoshi reopened this Mar 14, 2023
@asajoshi
Copy link
Contributor Author

@turkenf Can you check the PR now ? I have added some more instructions to test it.

Copy link
Member

@muvaf muvaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Though I'd like @ulucinar or @sergenyalcin 's approval before merge as it's been quite a while since I contributed this repo.

@sergenyalcin
Copy link
Collaborator

Let me trigger an end-to-end test to be sure that we do not break anything.

@sergenyalcin
Copy link
Collaborator

/test-examples="examples/resource/resourcegroup.yaml"

Copy link
Collaborator

@sergenyalcin sergenyalcin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @asajoshi LGTM!

@asajoshi
Copy link
Contributor Author

can we merge it today ? @sergenyalcin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for OIDC / Azure Workload Identity Authentication
5 participants