argoproj / argo-cd

Declarative Continuous Deployment for Kubernetes
https://argo-cd.readthedocs.io
Apache License 2.0
17.34k stars 5.27k forks source link

Declarative token creation #9884

Open CRASH-Tech opened 2 years ago

CRASH-Tech commented 2 years ago

Summary

Declarative create static tokens

Motivation

I'm using helm for create app projects and roles. Then I create token by hands, which call argo-cd from CI. It's a pain and not declarative.

Proposal

Keep static tokens in secret or AppProject CRD.

crenshaw-dev commented 2 years ago

Tokens are signed with the API server's key, so they must be generated at runtime. You can always declaratively store the tokens in Secrets using SealedSecrets or something similar.

todaywasawesome commented 2 years ago

@CRASH-Tech I agree with @crenshaw-dev here. Argo CD is setup so you can use your own secrets solution for this which is a better solution than trying to get everyone to use one specific one or to reinvent the wheel with something new.

CRASH-Tech commented 2 years ago

Tokens are signed with the API server's key, so they must be generated at runtime. You can always declaratively store the tokens in Secrets using SealedSecrets or something similar.

How I can do it?

crenshaw-dev commented 2 years ago

@CRASH-Tech I assume you're currently generating a token with something like argocd proj role create-token. After generating it, you'd just store it in any mechanism that allows you to generate a Secret (such as in a SealedSecret if you have that controller installed, or in Vault if you have a Vault controller installed, etc.). Once it's in a Secret in Kubernetes, you can reference it wherever you need it.

CRASH-Tech commented 2 years ago

@CRASH-Tech I assume you're currently generating a token with something like argocd proj role create-token. After generating it, you'd just store it in any mechanism that allows you to generate a Secret (such as in a SealedSecret if you have that controller installed, or in Vault if you have a Vault controller installed, etc.). Once it's in a Secret in Kubernetes, you can reference it wherever you need it.

I creating AppProjects and Applications from CI, and than that CI pipeline uses cli for sync and other commands for argo-cd. And I have a stage between creating appProject and it's token for cli

crenshaw-dev commented 2 years ago

If your CI is already capable of creating AppProjects and Applications, then it is effectively admin. What is the need for the project token / where is that token eventually used?

CRASH-Tech commented 2 years ago

If your CI is already capable of creating AppProjects and Applications, then it is effectively admin. What is the need for the project token / where is that token eventually used?

I can't manual sync or refresh over crd's. Only over cli.

crenshaw-dev commented 2 years ago

Ah! So you want to create a project token with only Kubernetes access, not Argo CD access. You could

1) add accounts.some-username: apiKey, login to argocd-cm 1) add accounts.some-username.password: 'some-bcrypted-password' to argocd-secret 1) after creating an AppProject, log in to Argo CD with the CLI using the newly-created account 1) use the CLI to create a project token 1) use the project token to do your syncs/refreshes 1) delete the account?

It's a bit janky, but I think it would accomplish what you're trying to do.

iamyeka commented 1 year ago

I got the same case. I need to specify the token when doing helm installation. After the installation, i can simply use the token in my program to create application or other things.

ArjonBu commented 1 year ago

@crenshaw-dev after the deletion of server.secretkey, then the token will not work anymore.

kilosonc commented 1 year ago

@CRASH-Tech Here my solution

  1. add serverSignature to argocd-secret which used to generate jwt token.
  2. generate a token
  3. add accounts.{accountName}.tokens to argocd-secret, takes claims id, iat from token, and set it as accounts.{accountName}.tokens's value, like this [{"id":"bd05a278-2c86-4047-9bd8-ef64209dffa5","iat":1673236464},{"id":"865d160e-288f-4edb-bb82-02278a5fa070","iat":1673255112}] after that, you can use your token freely
jakirpatel commented 1 year ago

+1 btw is there any document to understand how to statically declare the token ?

quintonn commented 1 year ago

@kilosonc could you please elaborate on step 2, generate token?

I'm trying to add a token as part of a cdk script, and this ticket is the only reference I have found with instructions for adding a password and token into the instance. The password code works, and I want to also add and test the token component.

Also, what library would generate the serverSignature and should it be added to the values.yaml config too?

jackmtpt commented 1 year ago

@crenshaw-dev The documentation (https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#projects) says that you can create JWT tokens declaratively, but it seems that these are impossible to actually use? The token isn't output by kubectl apply nor is it persisted anywhere. Is it actually possible to do this or should we not bother declaring the jwtTokens section in the AppProject and creating the tokens manually afterwards?

I also found this PR https://github.com/argoproj/argo-cd/pull/11736 that was never merged that suggests the jwtTokens field is deprecated and that we shouldn't use it at all - is that correct?

crenshaw-dev commented 1 year ago

@jackmtrayport I'm not sure the docs say you can create the tokens declaratively. As a matter of fact, I think they say the opposite:

    # NOTE: JWT tokens can only be generated by the API server and the token is not persisted
    # anywhere by Argo CD. It can be prematurely revoked by removing the entry from this list.

I opened https://github.com/argoproj/argo-cd/pull/11736 and then realized I didn't have enough context to understand the change, so I closed it.

crenshaw-dev commented 1 year ago

I think it would be easy enough to create a small controller to generate tokens and save them to Secrets. The controller could either call the Argo CD API Server or just directly use the server.secretKey and re-implement JWT generation.

I'm trying to decide whether I think that's a good feature to add to Argo CD itself. Feels more like an argoproj-labs thing, since JWT creation/maintenance doesn't fit neatly into any existing Argo CD component.

jackmtpt commented 1 year ago

I'm not sure the docs say you can create the tokens declaratively. As a matter of fact, I think they say the opposite:

So my reading of the text was that it's just warning you that you e.g. can't specify a token up-front and it has to be created by the API server which then doesn't persist it, not that you can't create them declaratively at all. The example yaml containing the jwtTokens: entry does apply and creates a token that you can see in the Argo UI, it's just unusable since you cannot get the value.

I think it would be easy enough to create a small controller to generate tokens and save them to Secrets. The controller could either call the Argo CD API Server or just directly use the server.secretKey and re-implement JWT generation.

That seems fairly sensible - given that Argo already does write back to Secrets for the initial admin password, and in a world where you want to try and configure things via Git as much as possible it does feel like a limitation that you can't declare what tokens you want to exist.

Either way though I think the docs should be updated to make it clear that while you can specify jwtTokens in a yaml that you kubectl apply to your cluster, you shouldn't do it because it's absolutely pointless (and that section of the example yaml should be removed).

crenshaw-dev commented 1 year ago

The example yaml containing the jwtTokens: entry does apply and creates a token that you can see in the Argo UI

My guess is that it's meant to go the other way around: when you create a token, Argo CD adds an entry to jwtTokens which you can then delete to disable the token. But if you add an entry yourself, no token is actually ever created.

Either way though I think the docs should be updated to make it clear that while you can specify jwtTokens in a yaml that you kubectl apply to your cluster, you shouldn't do it because it's absolutely pointless (and that section of the example yaml should be removed).

Yep, the docs should be updated. I'm not sure we should remove the YAML entirely, since it does communicate useful functionality (disabling a previously-created token). But it should be reworded to indicate that the field doesn't actually create any tokens.

zeusal commented 7 months ago

About this, where `do you store the token generated through the API?

leoandrea7 commented 1 month ago

Any news?