Spring Cloud Data Flow in AKS using ACR with a managed identity : metadata - spring-cloud-dataflow

We have a Spring Cloud Data Flow server (SCDF) deployed in an Azure Kubernetes Service (AKS).
We defined a user managed identity assigned to this AKS.
This identity has the AcrPull role on an Azure Container Registry (ACR) that doesn't have an admin user.
In the SCDF documentation, only the authorization type 'basicauth' is described :
- spring.cloud.dataflow.container.registry-configurations[myazurecr].registry-host=tzolovazureregistry.azurecr.io
- spring.cloud.dataflow.container.registry-configurations[myazurecr].authorization-type=basicauth
- spring.cloud.dataflow.container.registry-configurations[myazurecr].user=[your Azure registry username]
- spring.cloud.dataflow.container.registry-configurations[myazurecr].secret=[your Azure registry access password]
But as we use an user managed identity, we don't have a user/secret.
We tried the authentication type 'anonymous' without success.
How to configure the SCDF to be authorized to get the metadata of the container application ?

It works by defining a service principal and using its application ID and secret.
- spring.cloud.dataflow.container.registry-configurations[myazurecr].registry-host=myazureacr.azurecr.io
- spring.cloud.dataflow.container.registry-configurations[myazurecr].authorization-type=basicauth
- spring.cloud.dataflow.container.registry-configurations[myazurecr].user=[service principal application ID]
- spring.cloud.dataflow.container.registry-configurations[myazurecr].secret=[service principal secret]

If you are always using the private registry you can configure a secret directly in AKS and reference it using:
spring.cloud.deployer.kubernetes.imagePullSecret
or
spring.cloud.deployer.kubernetes.imagePullSecrets

Related

Dapr Secretstore with Azure Keyvault in Azure Kubernetes not working

I am trying to use secret store component with Azure Keyvault in my Azure Kubernetes Cluster. I setup exactly following the "https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/" but I am not able to retrieve the secrets. When I change the secretstore to local file or kubernetes secrets everything works fine. With Azure key vault I am getting the following error:
{
"errorCode": "ERR_SECRET_GET",
"message": "failed getting secret with key {keyName} from secret store {storename}: azure.BearerAuthorizer#WithAuthorization: Failed to refresh the Token for request to https://{vault url}/secrets/{secret key}/?api-version=2016-10-01: StatusCode=404 -- Original Error: adal: Refresh request failed. Status Code = '404'. Response body: getting assigned identities for pod {podname} in CREATED state failed after 16 attempts, retry duration [5]s. Error: <nil>\n"
}
I verified that the Client secret I am using is correct. Can anyone please point me to right direction ?
The error indicates that the service principal does not have access to get the secrets from the key vault
You can use System Assigned Managed Identity for the AKS pod and add the access policy to read the key vault secrets
Also, you can use Service Principal with access policy to read the key vault secrets or Key Vault Crypto Officer role so that you can fetch the key vault secrets
Reference: Azure Key Vault secret store | Dapr Docs

AKS Pod fail to access Azure Key Vault

I have a Dockerfile which has used to build a node project and run the "az login --service-principal" command. In this node project, it will retrieve the secret value from Azure Key Vault.
I try to run this docker image locally and it can successfully return the secret I set on Azure Key Vault. However, after I deploy the same docker image to AKS, it returns 403 forbidden error. Why would it happen?
I understand that I may not use this method to get authenticated to Azure Key Vault, but why it fails?
403 forbidden error means that the request was authenticated (it knows the requesting identity) but the identity does not have permission to access the requested resource. There are two causes:
There is no access policy for the identity.
The IP address of the requesting resource is not approved in the key
vault's firewall settings.
As you are able to access the key vault from your local, it means the error is because of the key vault's firewall settings
Check your Azure Key Vault networking settings. If you allowed access from selected networks, make sure to add AKS VMSS scale set virtual network in the selected networks
Now, you would be able to access key vault secrets from your AKS pod

Azure RBAC and AKS not working as expected

I have create an AKS Cluster with AKS-managed Azure Active Directory and Role-based access control (RBAC) Enabled.
If I try to connect with the Cluster by using one of the accounts which are included in the Admin Azure AD groups everything works as it should.
I am having some difficulties when i try to do this with a user which is not a member of Admin Azure AD groups. What I did is the following:
created a new user
assigned the roles Azure Kubernetes Service Cluster User Role and Azure Kubernetes Service RBAC Reader to this user.
Execute the following command: az aks get-credentials --resource-group RG1 --name aksttest
When I then execute the following command: kubectl get pods -n test I get the following error: Error from server (Forbidden): pods is forbidden: User "aksthree#tenantname.onmicrosoft.com" cannot list resource "pods" in API group "" in the namespace "test"
In the Cluster I haven't done any RoleBinding. According to the docu from Microsoft, there is no additional task that should be done in the Cluster ( like for ex. Role definition and RoleBinding).
My expectation is that when a user has the above two roles assigned he should be able to have read rights in the Cluster. Am I doing something wrong?
Please let me know what you think,
Thanks in advance,
Mike
When you use AKS-managed Azure Active Directory, it enables authentication as AD user but authorization happens in Kubernetes RBAC
only, so, you have to separately configure Azure IAM and Kubernetes RBAC. For example, it adds the aks-cluster-admin-binding-aad ClusterRoleBinding which provides access to accounts which are included in the Admin Azure AD groups.
The Azure Kubernetes Service RBAC Reader role is applicable for Azure RBAC for Kubernetes Authorization which is feature on top of AKS-managed Azure Active Directory, where both authentication and authorization happen with AD and Azure RBAC. It uses Webhook Token Authentication technique at API server to verify tokens.
You can enable Azure RBAC for Kubernetes Authorization on existing cluster which already has AAD integration:
az aks update -g <myResourceGroup> -n <myAKSCluster> --enable-azure-rbac

AKS with managed identity. Need Service Principal to automate deployment using bitbucket pipeline

I have an AKS (Kubernetes cluster) created with a managed identity in Azure portal.
I want to automate deployment in the cluster using bitbucket pipelines. For this, it seems I need a service principal.
script:
- pipe: microsoft/azure-aks-deploy:1.0.2
variables:
AZURE_APP_ID: $AZURE_APP_ID
AZURE_PASSWORD: $AZURE_PASSWORD
AZURE_TENANT_ID: $AZURE_TENANT_ID
Is there a way to get this from the managed identity? Do I need to delete the cluster and re-create it with service principal? Are there any other alternatives?
Thanks!
Unfortunately, the managed identity can only be used inside the Azure Resources. And it seems the bitbucket pipeline should have the service principal with enough permissions first to access the Azure, then it can manage the Azure resources. And for AKS, you can't change the managed identity that you enable it at the creation into service principal.
So finally, you need to delete the existing AKS cluster and recreate a new cluster with a service principal. Then you can use the same service principal to access Azure and manage the AKS cluster.
I wanted to post this for anyone looking.
The OP asked here about retrieving the service principal details for a managed identity. While it is possible to retrieve the azure resource ID and also the "username" of the service principal, as #charles-xu mentioned using a managed identity for anything outside of Azure is not possible, and this is because there is no method to access the password (also known as client secret)
That being said, you can find the command necessary to retrieve your Managed Identity's SP name in case you need it, for example in order to insert it into another azure resource being created by Terraform. The command is documented here: https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-view-managed-identity-service-principal-cli

Obtain OAuth token using Service Connection

I'm using Azure DevOps to deploy a web app and perform database migrations for an SQL Database. I have a Service Connection setup, and am able to deploy Azure resources using the Azure CLI, e.g.
- task: AzureCLI#2
displayName: 'Deploy Azure resources'
inputs:
azureSubscription: 'My Service Connection'
scriptType: 'bash'
scriptLocation: inlineScript
inlineScript: ./deploy.sh
Now, I want to perform database migrations, and I want to use the Service Connection to authenticate (the App Registration has been granted access to the SQL Database). My understanding is that I can login to the SQL Database using an OAuth token - my problem is how to get that token using the Service Connection.
Note that I can't add a client secret to the Service Principal in Azure, and so can't make a REST call to /oauth2/token with a client_secret (I work in the enterprise space, and things are locked down).
Given the pipeline has access to the Azure DevOps Service Connection, my feeling is there must be some way to use it to get an OAuth token that's valid for the https://database.windows.net/ resource - but how?
You may try the solution in the following case: Azure Pipeline connect to SQL DB using service principal
Adding an Azure CLI task which retrieved the bearer token. Then passed
this to Azure Powershell task which used the token.
$token= & az account get-access-token --resource=https://database.windows.net --query accessToken
Write-Host("##vso[task.setvariable variable=sqlToken]$token")

Resources