<p>From our Tekton pipeline we want to use ArgoCD CLI to do a <code>argocd app create</code> and <code>argocd app sync</code> dynamically based on the app that is build. We created a new user <a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/#create-new-user" rel="nofollow noreferrer">as described in the docs</a> by adding a <code>accounts.tekton: apiKey</code> to the <code>argocd-cm</code> ConfigMap:</p>
<pre><code>kubectl patch configmap argocd-cm -n argocd -p '{&quot;data&quot;: {&quot;accounts.tekton&quot;: &quot;apiKey&quot;}}'
</code></pre>
<p>Then we created a token for the <code>tekton</code> user with:</p>
<pre><code>argocd account generate-token --account tekton
</code></pre>
<p>With this token as the <code>password</code> and the <code>username</code> <code>tekton</code> we did the <code>argocd login</code> like</p>
<pre><code>argocd login $(kubectl get service argocd-server -n argocd --output=jsonpath='{.status.loadBalancer.ingress[0].hostname}') --username=tekton --password=&quot;$TOKEN&quot;;
</code></pre>
<p>Now from within our Tekton pipeline (but we guess that would be the same for every other CI, given the usage of a non-admin user) we get the following error if we run <code>argocd app create</code>:</p>
<pre><code>$ argocd app create microservice-api-spring-boot --repo https://gitlab.com/jonashackt/microservice-api-spring-boot-config.git --path deployment --dest-server https://kubernetes.default.svc --dest-namespace default --revision argocd --sync-policy auto
error rpc error: code = PermissionDenied desc = permission denied: applications, create, default/microservice-api-spring-boot, sub: tekton, iat: 2022-02-03T16:36:48Z
</code></pre>

<p>The problem is mentioned in <a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/#local-usersaccounts-v15" rel="nofollow noreferrer">Argo's useraccounts docs</a>:</p>
<blockquote>
<p>When you create local users, each of those users will need additional
RBAC rules set up, otherwise they will fall back to the default policy
specified by policy.default field of the argocd-rbac-cm ConfigMap.</p>
</blockquote>
<p>But these additional RBAC rules could be setup the simplest <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/projects/" rel="nofollow noreferrer">using ArgoCD <code>Projects</code></a>. And with such a <code>AppProject</code> you don't even need to create a user like <code>tekton</code> in the ConfigMap <code>argocd-cm</code>. ArgoCD projects have the ability to define <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/projects/#project-roles" rel="nofollow noreferrer">Project roles</a>:</p>
<blockquote>
<p>Projects include a feature called roles that enable automated access to a project's applications. These can be used to give a CI pipeline a restricted set of permissions. For example, a CI system may only be able to sync a single app (but not change its source or destination).</p>
</blockquote>
<p>There are 2 solutions how to configure the <code>AppProject</code>, role &amp; permissions incl. role token:</p>
<ol>
<li>using <code>argocd</code> CLI</li>
<li>using a manifest YAML file</li>
</ol>
<h2>1.) Use <code>argocd</code> CLI to create <code>AppProject</code>, role &amp; permissions incl. role token</h2>
<p>So let's get our hands dirty and create a ArgoCD <code>AppProject</code> using the <code>argocd</code> CLI called <code>apps2deploy</code>:</p>
<pre><code>argocd proj create apps2deploy -d https://kubernetes.default.svc,default --src &quot;*&quot;
</code></pre>
<p>We create it with the <code>--src &quot;*&quot;</code> as a wildcard for any git repository (<a href="https://github.com/argoproj/argo-cd/issues/5382#issue-799715045" rel="nofollow noreferrer">as described here</a>).</p>
<p>Now we create a Project <code>role</code> called <code>create-sync</code> via:</p>
<pre><code>argocd proj role create apps2deploy create-sync --description &quot;project role to create and sync apps from a CI/CD pipeline&quot;
</code></pre>
<p>You can check the new role has been created with <code>argocd proj role list apps2deploy</code>.</p>
<p>Then we need to create a token for the new Project role <code>create-sync</code>, which can be created via:</p>
<pre><code>argocd proj role create-token apps2deploy create-sync
</code></pre>
<p>This token needs to be used for the <code>argocd login</code> command inside our Tekton / CI pipeline. There's also a <code>--token-only</code> parameter for the command, so we can create an environment variable via</p>
<pre><code>ARGOCD_AUTH_TOKEN=$(argocd proj role create-token apps2deploy create-sync --token-only)
</code></pre>
<p>The <code>ARGOCD_AUTH_TOKEN</code> will be automatically used by <code>argo login</code>.</p>
<p>Now we need to give permissions to the role, so it will be able to create and sync our application in ArgoCD from within Tekton or any other CI pipeline. <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/projects/#project-roles" rel="nofollow noreferrer">As described in the docs we therefore add policies to our roles</a> using the <code>argocd</code> CLI:</p>
<pre class="lang-sh prettyprint-override"><code>argocd proj role add-policy apps2deploy create-sync --action get --permission allow --object &quot;*&quot;
argocd proj role add-policy apps2deploy create-sync --action create --permission allow --object &quot;*&quot;
argocd proj role add-policy apps2deploy create-sync --action sync --permission allow --object &quot;*&quot;
argocd proj role add-policy apps2deploy create-sync --action update --permission allow --object &quot;*&quot;
argocd proj role add-policy apps2deploy create-sync --action delete --permission allow --object &quot;*&quot;
</code></pre>
<p>Have a look on the role policies with <code>argocd proj role get apps2deploy create-sync</code>, which should look somehow like this:</p>
<pre><code>$ argocd proj role get apps2deploy create-sync
Role Name:     create-sync
Description:   project role to create and sync apps from a CI/CD pipeline
Policies:
p, proj:apps2deploy:create-sync, projects, get, apps2deploy, allow
p, proj:apps2deploy:create-sync, applications, get, apps2deploy/*, allow
p, proj:apps2deploy:create-sync, applications, create, apps2deploy/*, allow
p, proj:apps2deploy:create-sync, applications, update, apps2deploy/*, allow
p, proj:apps2deploy:create-sync, applications, delete, apps2deploy/*, allow
p, proj:apps2deploy:create-sync, applications, sync, apps2deploy/*, allow
JWT Tokens:
ID          ISSUED-AT                                EXPIRES-AT
1644166189  2022-02-06T17:49:49+01:00 (2 hours ago)  &lt;none&gt;
</code></pre>
<p>Finally we should have setup everything to do a successful <code>argocd app create</code>. All we need to do is to add the <code>--project apps2deploy</code> parameter:</p>
<pre><code>argocd app create microservice-api-spring-boot --repo https://gitlab.com/jonashackt/microservice-api-spring-boot-config.git --path deployment --project apps2deploy --dest-server https://kubernetes.default.svc --dest-namespace default --revision argocd --sync-policy auto
</code></pre>
<h2>2.) Use manifest YAML to create <code>AppProject</code>, role &amp; permissions incl. role token</h2>
<p>As all those CLI based steps in solution 1.) are quite many, we could also <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/projects/#configuring-rbac-with-projects" rel="nofollow noreferrer">using a manifest YAML file</a>. Here's an example <code>argocd-appproject-apps2deploy.yml</code> which configures exactly the same as in solution a):</p>
<pre><code>apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: apps2deploy
  namespace: argocd
spec:
  destinations:
    - namespace: default
      server: https://kubernetes.default.svc
  sourceRepos:
    - '*'
  roles:
    - description: project role to create and sync apps from a CI/CD pipeline
      name: create-sync
      policies:
      - p, proj:apps2deploy:create-sync, applications, get, apps2deploy/*, allow
      - p, proj:apps2deploy:create-sync, applications, create, apps2deploy/*, allow
      - p, proj:apps2deploy:create-sync, applications, update, apps2deploy/*, allow
      - p, proj:apps2deploy:create-sync, applications, delete, apps2deploy/*, allow
      - p, proj:apps2deploy:create-sync, applications, sync, apps2deploy/*, allow
</code></pre>
<p>There are only 2 steps left to be able to do a successful <code>argocd app create</code> from within Tekton (or other CI pipeline). We need to <code>apply</code> the manifest with</p>
<pre><code>kubectl apply -f argocd-appproject-apps2deploy.yml
</code></pre>
<p>And we need to need to create a role token, ideally assigning it directly to the <code>ARGOCD_AUTH_TOKEN</code> for the <code>argocd login</code> command (which also needs to be done afterwards):</p>
<pre><code>ARGOCD_AUTH_TOKEN=$(argocd proj role create-token apps2deploy create-sync --token-only)
</code></pre>
<p>The same <code>argocd app create</code> command as mentioned in solution 1.) should work now:</p>
<pre><code>argocd app create microservice-api-spring-boot --repo https://gitlab.com/jonashackt/microservice-api-spring-boot-config.git --path deployment --project apps2deploy --dest-server https://kubernetes.default.svc --dest-namespace default --revision argocd --sync-policy auto
</code></pre>
