weixin_39633500
weixin_39633500
2020-12-27 02:14

Flexible jwt authenticator

As a conjur admin, I want a more flexible jwt authenticator, so that I can use any metadata within a JWT as a host identity.

SUMMARY: The proposed azure authenticator flow does the following: Client sends JWT to conjur and conjur will then fetch and parse specific attributes from the JWT and then validate the parsed information with the hosts annotations. This process seems like it could be made more generic to support not just azure JWT but any JWT. Here is a sample policy I made. I am creating an authn-jwt authenticator that allows the ability to authenticate using subscription-id, resource-groupand resource-name. jsonPath is used to parse the attributes and then we can use regex to granularly obtain information within a json attribute.

GIVEN the policy

yaml
- !policy
  id: conjur/authn-jwt/azure-resource-name
  body:
  - !webservice
    annotations:
      # provider uri will be defined in annotations
      provider-uri: https://sts.azure.com/tenantID

      # the jwt is json,
      # so lets first parse with jsonPath
      # and then if we need to be more granular use
      # methods such as split or regex
      subscription-id/parse: $.sub

      # xms_mirid is a more complex attribute
      # and we must use the split method to
      # receive the needed resource group.
      # And a regex method for more 
      # complex attributes.
      resource-group/parse: $.xms_mirid
      # splitting on parsed attribute
      resource-group/parse/split: /
      # fetching this index from the array of the split
      resource-group/parse/index: 4

      # lets say I want to use regex
      resource-name/parse: $.xms_mirid
      # regex should only supports 1 match group 
      resource-name/parse/regex: .*\/(.*)$
      # only 1 match should be returned in this use case
      resource-name/parse/index: 0
  - !group apps
  - !permit
    role: !group apps
    resource: !webservice
    privilege: [ read, authenticate ]

- !host
  id: cyberark/azure/example_vm
  annotations:
    subscription-id: 24d6c3d7-d3eb-4973-b899-974bf79f48a
    resource-group: Conjur-ResourceGroup
    resource-name: ExampleVM

- !grant
  role: !group conjur/authn-oidc/azure-resource-group/apps
  member: !host cyberark/azure/example_vm

# now when `!host app1` authenticates the `subscription-id`, `resource-group` and `resource-name` will be validated and a conjur session token will be returned.

WHEN The authn-jwt/azure-resource-name is configured and enabled

THEN The following JWT should successfully authenticate to conjur

json
{
  "aud": "https://management.azure.com/",
  "iss": "https://sts.windows.net/df242c82.../",
  "iat": 157,
  "nbf": 157,
  "exp": 157,
  "aio": "42Vg...",
  "appid": "7230cc60...",
  "appidacr": "2",
  "idp": "https://sts.windows.net/df242c82...",
  "oid": "14751f4a...",
  "sub": "24d6c3d7-d3eb-4973-b899-974bf79f48a",
  "tid": "df242c82...",
  "uti": "g1mKQ0DE...",
  "ver": "1.0",
  "xms_mirid": "/subscriptions/24d6c3d7-d3eb-4973-b899-974bf79f48a/resourceGroups/Conjur-ResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ExampleVM"
}

I still think having default authenticators for each cloud provider such as iam, azure and gcp with jwt pre configured to the highest security standard is best. This solution would give us the ability to authenticate JWTs from any vendor.

On the conjur core side I think creating a jwt_validator class would be beneficial. An example of implementation below:


subscription_id_attr = {
  "annotation": "subscription-id",
  "json_path": "$.sub"
}
resource_group_attr = {
  "annotation": "resource-group",
  "json_path": "$.xms_mirid",
  "regex": "/",
  "index": 4
}
resource_name_attr = {
  "annotation": "resource-name",
  "json_path": "$.xms_mirid",
  "split": ".*\/(.*)$",
  "index": 0
}
expected_attributes = [
  subscription_id_attr,
  resource_group_attr,
  resource_name_attr
]
validated = jwt_validator(jwt, host_annotations, expected_attributes)
raise Err::Jwt_Validation_Error if !validated

该提问来源于开源项目:cyberark/conjur

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

6条回答

  • weixin_39633500 weixin_39633500 4月前

    Having a JWT authenticator would allow me to remove secret zero for many DevOps products that already have a certificate and private key. We could integrate with these products, generate a JWT (from the present private key) which can then be used to authenticate to conjur to then fetch secrets. This removes the need to pass around API keys to these devops tools.

    点赞 评论 复制链接分享
  • weixin_39577422 weixin_39577422 4月前

    👍👍

    点赞 评论 复制链接分享
  • weixin_39603117 weixin_39603117 4月前

    I do think JWT authn is the right way to go but I would dream of a way to "inherit" a basic jwt authn in a way that support authenticators that can be built on top of it that speak a native language of the target. I'll give a HL example Given a simple jwt autenticator I as a developer can contribute easily an Azure authenticator so that the hosts will have reasonable host annotations.

    for example authn-azure inherits authn-jwt according to these configurations [{ "annotation": "resource-group", "json_path": "$.xms_mirid", "regex": "/", "index": 4 }, { "annotation": "resource-name", "json_path": "$.xms_mirid", "split": ".\/(.)$", "index": 0 }] WDYT?

    点赞 评论 复制链接分享
  • weixin_39633500 weixin_39633500 4月前

    Where would

    
    [{
    "annotation": "resource-group",
    "json_path": "$.xms_mirid",
    "regex": "/",
    "index": 4
    },
    {
    "annotation": "resource-name",
    "json_path": "$.xms_mirid",
    "split": "./(.)$",
    "index": 0
    }]
    

    Be applied? All of this information should be configured on the policy itself and not implement within ruby code. Conjur admins typically are not well versed in ruby meaning that configuration should be applied on the policy level.

    Thanks, Andrew

    点赞 评论 复制链接分享
  • weixin_39603117 weixin_39603117 4月前

    we have discussed this today in the design review of Azure authenticator: https://github.com/cyberark/conjur/pull/1288 The scope you are describing here is Azure specific I would suggest an even more generic approach for an JWT authenticator. a mechanism where you can specify a field in the JWT by which you would like to authenticate and its value. in Azure this field can be subscription id but in another identity provider it could be "myIdentity". WDYT?

    点赞 评论 复制链接分享
  • weixin_39633500 weixin_39633500 4月前

    This example is azure specific but it can be applied to any JWT.

    What I am proposing is to parse the JWT using jsonPath and further parsing should be done with actions like regex or split all defined within the authenticators !webservice annotations.

    点赞 评论 复制链接分享

相关推荐