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

Federated identity credentials support for wildcards #373

Open
nclaeys opened this issue Feb 15, 2022 · 167 comments
Open

Federated identity credentials support for wildcards #373

nclaeys opened this issue Feb 15, 2022 · 167 comments
Labels
aad enhancement New feature or request

Comments

@nclaeys
Copy link
Contributor

nclaeys commented Feb 15, 2022

Is your feature request related to a problem? Please describe.
We are porting our product from AWS to Azure and in AWS you can use wildcards in your trust relationships between your serviceaccount and a role (similar to azure ad application in azure) as follows:

  statement {
    actions = [
    "sts:AssumeRoleWithWebIdentity"]
    effect = "Allow"

    condition {
      test     = "StringLike"
      variable = "<oidc_url>"
      values = [
      "system:serviceaccount:environmentprefix-*:saprefix-*"]
    }

    principals {
      identifiers = [<oidc_arn>]
      type = "Federated"
    }
  }

Is this something that you are considering as well? At the moment it is rigid to work with federated identity credentials in Azure:

  • 1 ad application can only have 20 federated identity credentials
  • you need to create a federated identity credential when deploying an application to a different aks environment.

Describe the solution you'd like
It would be great if the federated identity credential had support for wildcards to for example allow multiple environments or allow creating a dedicated service account for each pod.
An example of a credential could be as follows:
resource "azuread_application_federated_identity_credential" "app" { application_object_id = azuread_application.object_id display_name = "uuid" audiences = ["api://AzureADTokenExchange"] issuer = var.oidc_issuer_url subject = "system:serviceaccount:*:service_account_name-????" }
wildcard support: * for any string or ? for 1 random character

Describe alternatives you've considered
The other path we are thinking of is managing the federated identity credentials using a kubernetes operator. This way we can dynamically create the federated identity credential, when an application is deployed to a new environments.
Issues we see there are:

  • We could bump to the limit of only allowing 20 federated identity credentials per ad application.
  • Our clients might want to keep control over the federated identity credentials that get created for an azure ad application.
  • We notice a delay between the creation of federated identity credential and when it can be used, this might impact the jobs being launched on a new environment.

Additional context

@nclaeys nclaeys added the enhancement New feature or request label Feb 15, 2022
@aramase aramase added the aad label Feb 15, 2022
@ekristen
Copy link

I really need this. I was going to go down the creating of federated credentials but the limit of 20 is going to kill me. I need my pods to use different service accounts and sometimes these are dynamically created.

Anything you can do to add in support on AAD side to allow wildcards on this would be HUGE! Thanks.

@ekristen
Copy link

@aramase I see you added the label aad -- is there a change this gets supported, especially since this has nothing to do with the kubernetes webhook and everything to do with the aad side of things in Azure? Thanks!

@aramase
Copy link
Member

aramase commented Feb 17, 2022

Thank you for the feedback. I've shared this issue with the AAD team and will update the issue here once I hear from them.

cc @udayxhegde

@ekristen
Copy link

ekristen commented Mar 1, 2022

@aramase any update from the AAD team? Thanks.

@udayxhegde
Copy link

@ekristen thanks for the feedback! We will consider this support in our future planning cycles. Right now, we are heads down on completing the work needed to allow customers to use this capability in production for both app registration and managed identities.

@ekristen
Copy link

@udayxhegde appreciate the information and that you are heads down. I think without supporting wildcards you are going to extremely limit people's ability to use this. Service Accounts are often created in larger quantities per workload even to help with permission restrictions and other needs, not being able to wildcard service accounts is very very limiting.

Has there been any further discussion in supporting this and if so any ETA? Thank you.

@udayxhegde
Copy link

Hi @ekristen : thanks for your feedback. In our initial release we will not be able to support wildcards unfortunately. The additional support in the form of wildcards or custom claims is indeed very important: but there's no ETA for that support.

@ekristen
Copy link

@udayxhegde alright, that's unfortunately. I'll have to fallback to using secrets or certificates, with the limit of 20 federated identities and no wildcards, while this is the preferred way to auth, it's not usable which is unfortunate. If there's someone I can elevate this to to get higher priority via my company, please let me know. Thanks.

@udayxhegde
Copy link

@ekristen : are there no other options to consider here? Since each pod can only use one service account, what is causing you to intentionally use different service accounts or create them dynamically? I am sure there is a good reason why this is being done, just trying to understand it.

@ekristen
Copy link

Maybe there is, any chance the limit of 20 federated identities can be increased for an app? Like 250?

We are also using a service principal to target a couple different tenants as well.

We have a lot of automation and various workloads that need specific access to resources within the the cluster, this all happens via automated means.

This ends up meaning that we have 20-100+ (this number will grow) different workloads with service accounts that can access specific resources like dedicated secrets or config maps.

This is why we can't use a single service account.

If the limit of 20 federated identities wasn't there I might be able to make this work.

I started down the path of dynamically editing the federated identities until I ran into the 20 limit.

@udayxhegde
Copy link

changing by that order of magnitude is not practical: another alternative is to use multiple service principals, but that is not easy to manage either.

@ekristen
Copy link

The wildcard is the best approach and least amount of work for the Azure team by far. I'm unfortunately going to have to use certificates or shared secrets until wildcards are supported which is a huge bummer. Hopefully it won't take long to implement, it's not a very complex mechanism and is going to unlock you and your customers a ton to do more amazing integrations.

@ekristen
Copy link

@udayxhegde following up on this, I thought of another user-case/reason this is needed. For teams that are helping to manage or do things in multiple tenants.

Use Case: I'm a company with a product to help people with Azure, our software is deployed and managed on k8s and needs to use a single service principal (or two) to talk to dozens if not hundreds of other tenants.

AZWI would be the best from a security perspective, but since only the service account can change the tenant being targeted, and since wildcards aren't supported and the limit on federated identities is 20 this can't be used, unfortunately that means hard coded certificates or secrets. :(

@ekristen
Copy link

@udayxhegde any movement on this feature request?

@smokedlinq
Copy link

Just hit this after a few GitHub repos converted. What's the recommended best practice for a GitHub repo? One per repo? Was hoping one per team would be sufficient, especially when the team repos would be given the same permission to Azure and app resources.

@ekristen
Copy link

ekristen commented Aug 9, 2022

You have to do one federated identity per repo and limited to 20 per app, then you have to create another one. Unfortunately this is a very painful feature to use.

@ekristen
Copy link

ekristen commented Sep 1, 2022

@udayxhegde is there anyone we can elevate with this on the Azure side and put in direct contact with. To be very honest, this feature is useless at scale. Without wildcard support, it's just easier and better to use hard coded client secrets/certificates which is a shame.

@salaxander
Copy link
Contributor

salaxander commented Sep 8, 2022

Hey @ekristen - would you maybe be willing to have a chat with me on this? I'm not on the Azure Identity team, but I am the PM for Workload ID at Microsoft, so I'd really love to be sure I've got your use case well understood and documented to maybe help push this forward.

If you're on Kubernetes Slack you're welcome to ping me there (@ Xander), otherwise xgrzywinski @ microsoft.com

@ekristen
Copy link

ekristen commented Sep 8, 2022

Hey @ekristen - would you maybe be willing to have a chat with me on this? I'm not on the Azure Identity team, but I am the PM for Workload ID at Microsoft, so I'd really love to be sure I've got your use case well understood and documented to maybe help push this forward.

If you're on Kubernetes Slack you're welcome to ping me there (@xander), otherwise xgrzywinski @ microsoft.com

Absolutely! I'll reach out.

@udayxhegde
Copy link

Sorry @ekristen for the late reply... I recognize this capability is important to manage things at scale, but unfortunately, we don't have any updates on this yet.

@kevinharing
Copy link

kevinharing commented Dec 14, 2022

This is holding us back as well. We deploy resources dynamically at request with a pre-existing managed identity. The namespace name is dynamic and is unique for each deployment. The service account is created in this namespace. It is really cumbersome to have to create/delete the federated identity credential for each deployment, and of course there's the limit of 20 credentials. Also, the delay in identity/credential propagation is exactly what we're trying to fix by moving away from AAD Pod Identity. A wildcard for the namespace name would fix this problem, as we would be able to have a pre-existing federated identity credential that can be reused.

@ekristen
Copy link

I had a call with a PM a few months back on this. I said match what AWS does, allow wildcards anywhere, or StringLike matching. This is still a HUGE pain point.

@salaxander salaxander removed this from Roadmap Jan 17, 2023
@kevinharing
Copy link

@salaxander So no plan for implementing this for now? Is there a workaround?

@prashant-rathi
Copy link

Dear Microsoft Team,

You should consider adding wildcard support. So many people are interested and this seems to be a blocker for many of us.
Not sure why it is not picked in years!!

@liam-screencloud
Copy link

Wildcard please....

@ben-silvatech
Copy link

Desperately in need of wildcard support!

@Halama
Copy link

Halama commented Oct 22, 2024

We’ve also encountered this issue where we cannot use wildcards, specifically in branch names.

In our case, we use GitHub Actions to deploy infrastructure via Terraform across multiple environments in GCP, AWS, and Azure. Our goal is to bind identities to the environment name and either any branch or the main branch, as follows:

  • Environment + any branch: Read-only permissions (used for executing Terraform plan from PRs).
  • Environment + main branch: Write permissions for Terraform apply.

We successfully achieved this in GCP (by defining multiple attributes on different claims and binding permissions to them) and in AWS (by using wildcards in branch name matching in the IAM role trust policy).

Unfortunately, this is not possible in Azure.

@ukhan262
Copy link

When will the allowance for more than 20 identities be provided? Not sure why is this even a restraint at this point.

@morfien101
Copy link

Without this wild card support, oidc integration with github is rudimentary at best and basically unsable.

After 2 and a half years since being reported to the team and "heads down trying to implement it" we can't just do a regex match on the subject? So rather let the customers just fall back to storing secrets and let the docs tell them not to.

@aramase @udayxhegde If you are still here, is this issue ever going to get some dev time?

@imar-io
Copy link

imar-io commented Nov 22, 2024

Please add this feature... Works in AWS for a long time...

@jcrichlake
Copy link

Can we get an update on this issue? It seems like people are consistently running into this issue and it's been two years since this issue was initially created. There's also been several people asking for an update on whether or not this will be supported or not. At the least let us know if you won't be supporting this much needed feature.

@Vegoo89
Copy link

Vegoo89 commented Dec 2, 2024

@nickludwig is there private preview going on? Are you still main point of contact for this feature in Microsoft?

Would be great if someone provides at least some update about this feature status

@perlboy
Copy link

perlboy commented Dec 2, 2024

No thanks to Azure but flagging that this comment is an interim solution enabled on the GitLab side. Requires minor change on AWS (if you're multicloud) to align but gets a terraform plan with Azure across the line in PRs.

@ben-silvatech
Copy link

I know @merill is Principal Product Manager for Entra, tagging in case he can shed some light

@nickludwig
Copy link

Hey all, a bit of a long post incoming.

We are in the process of building out wildcard support (as part of a feature we're calling Flexible FIC) and have some functionality that's ready to test. Given docs aren't out yet (likely will be released next week), I'm including all relevant information here so you can begin testing as you see fit.

For more context, we're extending the FIC object with a new property called claimsMatchingExpression. This property enables the use of a wildcard-based expression for matching against a specified claim. There will be a few limitations when this first rolls out, and a few pieces coming at a later point as implementation work finishes up.

The claimsMatchingExpression property is comprised of two pieces; value, which contains the expression, and languageVersion which allows us to version the expression language (should always be set to 1 for now). The expression itself is comprised of three pieces; a claim lookup (represented as "claims['sub']"), an operator (matches is the operator for wildcards), and the comparand (which is what the incoming token will be matched against).

A basic example of a Flexible FIC is as follows:

{
    "name": "myFlexibleFic",
    "issuer": "https://token.actions.githubusercontent.com",
    "audiences": [
        "api://AzureADTokenExchange",
    ],
    "claimsMatchingExpression": {
        "value": "claims['sub'] matches 'repo:contoso/contoso-repo:ref:refs/heads/*'",
        "languageVersion": 1
    }
}

The matches operator supports both single char (denoted by ?) and multi-char (denoted by *) wildcards. You can configure this via the Microsoft Graph /beta endpoint, or by using the Application Registrations Azure Portal UX.

NOTE: claimsMatchingExpression and subject fields are mutually exclusive. Whenever a claimsMatchingExpression is configured, the subject field must be null, and vice versa.

What is testable right now?

You can begin using this functionality for GitHub/GitLab/Terraform Cloud FIC's configured on application registrations. The following describes the supported issuer URL's/supported claim(s) for each issuer.

GitHub

Supported issuer URL's: https://token.actions.githubusercontent.com
Supported claims and operators per claim:

  • Claim sub supports operators eq and matches
  • Claim job_workflow_ref supports operators eq and matches

GitLab

Supported issuer URL's: https://gitlab.com, https://gitlab.example.com, https://gitlab.example.ca
Supported claims and operators per claim:

  • Claim sub supports operators eq and matches

Terraform Cloud

Supported issuer URL's: https://app.terraform.io, https://app.eu.terraform.io
Supported claims and operators per claim:

  • Claim sub supports operators eq and matches

NOTE 1: You will not be able to discover the API on your own, as the deployment to un-hide the API has not completed. That said, the allow-list gating access to this functionality has been removed, so you can configure these Flexible FIC's right now using the syntax mentioned in this post.

NOTE 2: To configure Flexible FIC's via App Registrations Azure Portal UX, you will need to include a feature flag in your portal URL for the time being. We are still waiting on the deployment to full release the UX to complete. The feature flag needed is enableFlexibleFIC=true, and an example of a portal URL containing this feature flag is https://portal.azure.com/?enableFlexibleFIC=true#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Credentials.

What is coming at a later point?

Flexible FIC for Managed Identities + AKS

We are currently in the process of implementing this functionality for FIC's configured on managed identities. When we release this, we will also enable AKS as a supported issuer for this functionality.

Our current estimate for completion of this work is the middle to end of CY25Q1. This is a bit fluid, so I will circle back if anything changes regarding that date.

Azure CLI support

In order to provide native support for this new functionality, Azure CLI needs a public API. Since the deployment to make the API public has not completed, Azure CLI cannot implement this functionality. That being said, you can use Azure CLI's az rest method for making REST requests with this new functionality. An example of this is as follows:

  • az rest --method post --url https://graph.microsoft.com/beta/applications/{objectId}/federatedIdentityCredentials --body "{'name': 'FlexFic1', 'issuer': 'https://token.actions.githubusercontent.com', 'audiences': ['api://AzureADTokenExchange'], 'claimsMatchingExpression': {'value': 'claims[\'sub\'] matches \'repo:contoso/contoso-org:ref:refs/heads/*\'', 'languageVersion': 1}}"

Terraform provider support

Same as with Azure CLI, Terraform needs a public API to begin work on providing native support. Once the deployment to un-hide the API has been completed, we will work on getting an ETA on this support.

Feedback/Questions

For any feedback or gaps in functionality that are not mentioned in this post, please fill out this form.

For any questions, please post them below. I will try and be as active as I can in this thread.

@sbgamma
Copy link

sbgamma commented Dec 6, 2024

Thanks @nickludwig for the update. There are a series of supported URL issuers above, but are there plans to enable this feature for arbitrary ("Public"?) issuers? I'm interested in implementing OIDC auth to orchestrate Azure automation from Bitbucket pipelines, where the OIDC issuer is https://api.bitbucket.org/2.0/workspaces/<slug>/pipelines-config/identity/oidc'.

@dhduvall
Copy link
Contributor

dhduvall commented Dec 6, 2024

@nickludwig Marvelous!

Will the ability to inspect arbitrary claims come with the initial release, or as a follow-on project "at a later point"? GitLab's token has a rich set of claims, but their sub is still not especially configurable, and it would be very nice to have access to the data in those claims. Should I fill out the feedback form (or file a support request) to help prioritize this?

@dhduvall
Copy link
Contributor

dhduvall commented Dec 6, 2024

az ad app federated-credential list is unhappy after the az rest command to add the FIC (or doing it through the portal); it seems to be unhappy about the subject field being `null, and then it trips over its own shoelaces because it tries to decode some invalid JSON to get at the error:

{"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#applications('UUID')/federatedIdentityCredentials",
"value":[{"id":"UUID","name":"FlexFic1","issuer":"https://gitlab.com"{"error":{"code":"InternalServerError","message":
"The property 'subject[Nullable=False]' of type 'Edm.String' has a null value, which is not allowed.","innerError":
{"date":"2024-12-06T23:19:12","request-id":"UUID","client-request-id":"UUID"}}}

Note "https://gitlab.com"{"error", so the stack trace you get tells you json.decoder.JSONDecodeError: Expecting ',' delimiter: line 1 column 247 (char 246).

The portal seems to be fine.

@nickludwig
Copy link

@sbgamma - This is something we're discussing but don't have a definitive answer for quite yet.

@dhduvall - So the initial release covers just the claims/issuers mentioned in my post. I'm open to extending this to other claims given sufficient justification, so feel free to fill out the form I included in the post. Like with arbitrary issuers, arbitrary claims are something I have as a goal, but don't have a definitive answer for yet.

As for the Azure CLI stuff - yep, az ad app federated-credential list is unfortunately not going to work until az ad app federated-credential is updated to support Flexible FIC. You should still be able to list FIC's using az rest and switching method to get, however.

@SiHaoShen
Copy link

@nickludwig Thank you for the update and truly appreciate that the wildcard support feature is finally here!

So I want to use flexible FIC wildcard in our repo under code.siemens.com (gitlab clone). I defined the body.json as following:

{
    "name": "code-siemens-fic",
    "issuer": "https://code.siemens.com",
    "audiences": [
        "https://code.siemens.com"
    ],
    "subject": null,
    "description": "code.siemens service account federated identity",
    "claimsMatchingExpression": {
        "value": "claims['sub'] matches 'repo:$repoProject/$repoName:ref:refs/heads/*'",
        "languageVersion": 1
    }
}

And when I try to create the FIC az rest --method POST --uri "https://graph.microsoft.com/beta/applications/$objectId/federatedIdentityCredentials" --body @body.json I get following error:

Bad Request({"error":{"code":"InvalidFederatedIdentityCredentialValue","message":"The FederatedIdentityCredential.ClaimsMatchingExpression.Value is invalid. Rule exception: Expression is not supported for applications in this cloud 'Public' using issuer 'https://code.siemens.com'. paramName: FederatedIdentityCredential.ClaimsMatchingExpression.Value, paramValue: claims['sub'] matches 'repo:$repoProject/$repoName:ref:refs/heads/*', objectType: Microsoft.Online.DirectoryServices.Application","innerError":{"date":"2024-12-09T10:52:36","request-id":"$requestId","client-request-id":"$client-request-id"}}})

What am I doing wrong here?

@nickludwig
Copy link

@SiHaoShen - the reason this is not working at the moment is because the issuer you've configured is not one of the generalized issuers we support for Flexible FIC at the current moment. The supported issuer URL's are mentioned in my post above. It is a goal to extend this support to arbitrary issuers, but it is not something I have a definitive answer for yet.

@nbaju1
Copy link

nbaju1 commented Dec 12, 2024

@nickludwig is Azure DevOps considered an arbitrary issuer (https://vstoken.dev.azure.com/<org_id> ), i.e. that it might not be supported for Flexible FIC?

@jgiasson-nuharbor
Copy link

jgiasson-nuharbor commented Dec 12, 2024

Hey @nickludwig , I also put my initial post in here for OIDC integration from BitBucket like SBGAMMA. If you do not do arbitrary URLs it would be nice to at least add BitBucket to the list of supported issuers https://api.bitbucket.org/2.0/workspaces/<slug>/pipelines-config/identity/oidc

@dhduvall
Copy link
Contributor

I'm trying to add this to an application using terraform, and struggling a bit. Obviously neither azurerm or azuread will support this, and normally for unsupported Azure resources I'd use azapi, but I don't see how to use azapi for an Entra object, and I don't know of another terraform provider which is fully flexible like that. Is hashicorp/terraform-provider-azuread#937 what I need?

@daisy-timms-xlab
Copy link

I'm trying to add this to an application using terraform, and struggling a bit. Obviously neither azurerm or azuread will support this, and normally for unsupported Azure resources I'd use azapi, but I don't see how to use azapi for an Entra object, and I don't know of another terraform provider which is fully flexible like that. Is hashicorp/terraform-provider-azuread#937 what I need?

@dhduvall I've used the restful_operation resource from this restful provider to set this via the beta graph api in terraform. It's not as clean as azapi or azurerm/azuread support, but it does the job in the interim :)

provider "restful" {
  base_url = "https://graph.microsoft.com/beta"
  security = {
    http = {
      token = {
        token = var.graph_api_token
      }
    }
  }
}

I run the following to set the graph api token:
TF_VAR_graph_api_token=$(az account get-access-token --resource-type ms-graph --query accessToken -o tsv)

Other rest/http terraform providers would likely also work.

@dhduvall

This comment has been minimized.

@perlboy
Copy link

perlboy commented Dec 16, 2024

Keeping the existing azuread_application_federated_identity_credential barfs due to invalid JSON in the return however, here's a hacked up version using az rest, terraform_data and jsonencode:

locals {
  project_path = "path/from/gitlab/com/base"
  flexible_fic = {
    name = "project-name"
    description = "Federated Identity credential for GitLab to perform Project Operations"
    issuer = "https://gitlab.com"
    audiences = ["https://gitlab.com"]
    subject = null
    claimsMatchingExpression = {
      value = "claims['sub'] matches 'project_path:${local.project_path}:ref_type:branch:*'"
      languageVersion = 1
    }
  }
  flexible_fic_json = replace(jsonencode(local.flexible_fic), "\"", "\\\"")
}

resource "terraform_data" "flexible_fic_hack" {
  input = {
    object_id       = azuread_application.main.object_id
    credential_name = local.flexible_fic.name
  }

  provisioner "local-exec" {
    command = <<EOT
    az rest --method post --url https://graph.microsoft.com/beta/applications/${azuread_application.project_application.object_id}/federatedIdentityCredentials --body "${local.flexible_fic_json}"
    EOT
  }

  provisioner "local-exec" {
    when    = destroy
    command = "az rest --method delete --url https://graph.microsoft.com/beta/applications/${self.input.object_id}/federatedIdentityCredentials/${self.input.credential_name}"
  }

}

At least with this there isn't an additional provider involved and you can do a depends on the resource while having a back-out plan once the terraform resource is updated to support it.

Edit: Refined to do lifecycle on destroy/create too.

@nickludwig
Copy link

@nbaju1 - not an arbitrary issuer, but just one that's currently unsupported. It'll be one of the ones we discuss when looking to expand this functionality, hoping to have those conversations at the beginning of the new year.

@jgiasson-nuharbor - yeah if you want to include some more info (justification, scenarios, etc) in the form I provided in my initial post, that'll help me when I discuss with folks on my end. if you want to include your email in the form, then I can reach out to you about this so we can discuss some more.

Also, thanks to all for including some examples of workarounds for using this with various tools!

@cgagnon-akx
Copy link

@SiHaoShen - the reason this is not working at the moment is because the issuer you've configured is not one of the generalized issuers we support for Flexible FIC at the current moment. The supported issuer URL's are mentioned in my post above. It is a goal to extend this support to arbitrary issuers, but it is not something I have a definitive answer for yet.

@nickludwig I hope other domains would supported quickly. I am in the same situation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aad enhancement New feature or request
Projects
None yet
Development

No branches or pull requests