|
| 1 | +# This example demonstrates usage of creds-init credentials to issue |
| 2 | +# git commands without a Git PipelineResource or git-clone catalog task. |
| 3 | +# |
| 4 | +# In order to exercise creds-init a sidecar is used to run a |
| 5 | +# git server fronted by SSH. The sidecar does the following things: |
| 6 | +# - Generates a host key pair, providing the public key to Steps for their known_hosts file |
| 7 | +# - Accepts a public key generated from creds-init credentials and uses that for an authorized_keys file |
| 8 | +# - Creates a bare git repo for the test git commands to run against |
| 9 | +# - Starts sshd and tails its log, waiting for the git commands to come in over SSH |
| 10 | +# |
| 11 | +# Two separate Steps then perform authenticated git actions against the sidecar |
| 12 | +# git server using the credentials mounted by creds-init: |
| 13 | + |
| 14 | +# The first step makes a git clone of the bare repository and populates it |
| 15 | +# with a file. |
| 16 | +# |
| 17 | +# The second step makes a git clone of the populated repository and checks |
| 18 | +# the contents of the repo match expectations. This step runs as a non-root |
| 19 | +# user in order to exercise creds-init credentials when a securityContext |
| 20 | +# is set. |
| 21 | +# |
| 22 | +# Notice that in each Step there is different code for handling creds-init |
| 23 | +# credentials when the disable-home-env-overwrite flag is "false" and when |
| 24 | +# it's "true". |
| 25 | +apiVersion: v1 |
| 26 | +kind: Secret |
| 27 | +type: kubernetes.io/ssh-auth |
| 28 | +metadata: |
| 29 | + name: ssh-key-for-git |
| 30 | + annotations: |
| 31 | + tekton.dev/git-0: localhost |
| 32 | +data: |
| 33 | + # This key was generated for this test and isn't used for anything else. |
| 34 | + ssh-privatekey: LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUJsd0FBQUFkemMyZ3RjbgpOaEFBQUFBd0VBQVFBQUFZRUF5T1g3ZG5OWlFBZVk4cHNMOXlaUnp3NXNDVG1yWGh6Zld1YTZuZ2VDQ0VRRTY4YjVUSThTCkNlbEhlNG9oTUtBdXZ0ZTE4YXJMK2EvVldpeFN6a2tBMmFIZVhkdUJ1bStkS2R2TlVVSUhNc1dOUythcENQYmE4R3ZGaHYKdG81Tkx0bWpxT2M0WjJkK1RPS3AvakMrS3pvUDFHQWdRL25QMitMTldabzlvTTc4TzQ3Z1dSem9FNlFKeGJqbFlPMHRMbwp4YXUxdTNrbUtsNSthbUxsNHpGN25wdmV1dGlSWDhmY2hGam5Ka2dqK3BVeFJvTGF4SDdDN0NTcDExWUkyMEhKRVFXeEk3CllaekNTYml5KzZ1a2l0Tk1MZ29qMnpSTGl2ZTVvZm9nenpYbkdWUUpZdUIzOFhQM0ZIQWMvOXhzUXdzd3dQS2hkQ3g4T0QKbjErYXpLOHp5SGhXK0dxckJhS1R4cDlrcVRpKzZSMWk4ZjVxOEt6NXpGVTZmd05qQXZ3STFBZ3IwS2FzU1JxWTVMcGxnTgpZcW1DY01JODZKUnRGWHRWWVQrT05tdWFhYUQ1QUErbnpkNW81R0haZTlFSlNqUThZMHZwbjhmNjNjeEw2RTdzVmxpMnpzCnNhN1RST2JMK3YyVnFuSlpEY2pIZXMzS1M5Mld0V3RJbXdXOG81VkRBQUFGaU04K0NUL1BQZ2svQUFBQUIzTnphQzF5YzIKRUFBQUdCQU1qbCszWnpXVUFIbVBLYkMvY21VYzhPYkFrNXExNGMzMXJtdXA0SGdnaEVCT3ZHK1V5UEVnbnBSM3VLSVRDZwpMcjdYdGZHcXkvbXYxVm9zVXM1SkFObWgzbDNiZ2Jwdm5TbmJ6VkZDQnpMRmpVdm1xUWoyMnZCcnhZYjdhT1RTN1pvNmpuCk9HZG5ma3ppcWY0d3ZpczZEOVJnSUVQNXo5dml6Vm1hUGFETy9EdU80RmtjNkJPa0NjVzQ1V0R0TFM2TVdydGJ0NUppcGUKZm1waTVlTXhlNTZiM3JyWWtWL0gzSVJZNXlaSUkvcVZNVWFDMnNSK3d1d2txZGRXQ050QnlSRUZzU08yR2N3a200c3Z1cgpwSXJUVEM0S0k5czBTNHIzdWFINklNODE1eGxVQ1dMZ2QvRno5eFJ3SFAvY2JFTUxNTUR5b1hRc2ZEZzU5Zm1zeXZNOGg0ClZ2aHFxd1dpazhhZlpLazR2dWtkWXZIK2F2Q3MrY3hWT244RFl3TDhDTlFJSzlDbXJFa2FtT1M2WllEV0twZ25EQ1BPaVUKYlJWN1ZXRS9qalpybW1tZytRQVBwODNlYU9SaDJYdlJDVW8wUEdOTDZaL0grdDNNUytoTzdGWll0czdMR3UwMFRteS9yOQpsYXB5V1EzSXgzck55a3ZkbHJWclNKc0Z2S09WUXdBQUFBTUJBQUVBQUFHQUNQSGtmbU9vWjZkdThlNWhYQUhDeHJ0WHFCCmwvUGROL1JtYmJqRW05U216czR5cWEwd1BUdzhrMU81VHM0V05nY1hMZFVRTlB6YkE4aWFWTGtvL0JqKzhiSFlhMmdmeVMKUE5qaWpXbXBOR09EWlF2Q0h2b095WUdpNjkycHovWnNTZCt0bEFzNm54LzY1ZjcwZHdVREJub0FjZnFLY28wQnVMRlNBKworamY5RnhISGYzQkFEUS9TdDVFQjlZelo1Q2F2cTRQcjZvS2w3R3RpbnRIbTZIbUlwTUlubWVEMnV3cjl2ZGZ1RGJhVDdYClVOSm10elVGck1uOUhlOWd1WkoyTXd3a015S09ScnRhVFA3VjFZK3FOM3ZncStmRkNtU0VkekxBU3BWTHMyL1hQTCtwTnAKTTVZUVRRMFJSZWdKTEdtTHZ0ZmpkK1RRMFQ0bjBucnBJVGRXRTRsL05sTG9taTVhUndzQXFtY2hZSGxhN0g3YlNyS2lKawpyWTg1RTliZm8wSXJqUDNQNzFYNmxjcTB0VDhDTklUQUNleWJQT3kwcDVDc3JwZTdhZEJBOXF4MTZjR2tkZ0NPWk9GMnRpCktoWWJHeTc4ei9YNEh2OEptVmhaSHF3RlFQQzVleWljbE1PTFJXNDJOcUJhNEVFc3RHT3l4MHZwa0lVS3VhRlJuQkFBQUEKd1FESytXYzU1WHVpWjgySXM5NnN2bWIrR0Y5c2pBRWVaWHpHSWpDL1NHVEhIWTZSQmc1TnlQOUdZNmtoWnBjd0cyTU52dQpZUjhuN0psRWlVanU2cjY2Smh0WGtvdTR4WlU1dDkvMlJvdHRmeWpKODJmYm8yTHZmNERUOVNvSURxZnk5VmlMSjhSWUNkCkt6NnpYSHFTZ1RBRU1vaUhjbFpIZzRqTitrOW1ma2tPMDBQbEJJaE1YU0ZMLzUrZUhGdStQTmxaU1g5NUlMRjJvZ0Y1RG0KWTFuaTRUOGJjdzY2dmFzamthcjFZekptM1VidEVnSzQ2VVllNGJac2NXbWt4dngwMEFBQURCQVA4UysyTmtheWkvb3NzVApTQXpJMi9QU2tJMDVEY1lTYnNOQjZ4a3pobzdKaDlHeUNvbW5xZ1IxR2ZBOTBqV3AxVks0TG43TmtYYWJaVmJPc0xoT21DCkdBbVRZTHRjaTB0bkhhYk5HTEZ3ZmdiUitqRzZNQ2p4cEh5anM5MDlKSHhtYmswbElpczdPN1N3VThERGcrSEVxc0EvNUoKQ1VMTWU3em9mNERhUnZXdFhTRks2ZW5LNnpGaHBINjVQY29TN0o0NjJhNzdUMDVGQXhMemNaRkc5VWZ5WUdMa1ZmdHRTTApNVDhudW9LaW5XTGNLSlVQeis1MjJlM3lIcis4c3pVUUFBQU1FQXlhQ28xSnRBcjRpczY0YTBuZTFUV0o0dXcyT3FDdUlDCm9acG1QN2UyRnh3bVRCSWMrbzZkSEVNVHo2c2ZZSkFxU2l4ZzYydXYzWlRTc25STWljaDZ0b1k0SVI4cWFMa1prLzU5cmEKQWFONFlvTkdpQTZxY0Jzc3NLMmZuM2YxRFJhckxPbWZHTnpTMU41S1RvSFVlUkVGWDExdHVNM1pqOGxTelFBOWZSakk1OQpFWmFnOWJaOXRJOEg5dmEvTGRMK3U3dTZZWkVRSEJCS1MxMW1tOVVXd1pDMkdUV3ZnNzRlTnRmemtZeDQxdlhIeTZBbW9ECmxuOHo2N3lvWEZzbEpUQUFBQURuTmpiM1IwUUcxbFkyZ3ViR0Z1QVFJREJBPT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg== |
| 35 | + # This known_hosts file doesn't actually get used; we overwrite it with the public key |
| 36 | + # of our temporary test git server. But it's required here because otherwise creds-init |
| 37 | + # calls ssh-keyscan which in turn tries to reach out over the network, will fail to make |
| 38 | + # contact with the localhost SSH server because it isn't running yet, and the TaskRun |
| 39 | + # will end in failure. |
| 40 | + known_hosts: Cg== |
| 41 | +--- |
| 42 | +apiVersion: v1 |
| 43 | +kind: ServiceAccount |
| 44 | +metadata: |
| 45 | + name: ssh-key-service-account |
| 46 | +secrets: |
| 47 | +- name: ssh-key-for-git |
| 48 | +--- |
| 49 | +apiVersion: tekton.dev/v1beta1 |
| 50 | +kind: TaskRun |
| 51 | +metadata: |
| 52 | + name: authenticating-git-commands |
| 53 | +spec: |
| 54 | + serviceAccountName: ssh-key-service-account |
| 55 | + taskSpec: |
| 56 | + volumes: |
| 57 | + - name: messages |
| 58 | + emptyDir: {} |
| 59 | + sidecars: |
| 60 | + - name: server |
| 61 | + image: alpine/git:v2.24.3 |
| 62 | + securityContext: |
| 63 | + runAsUser: 0 |
| 64 | + volumeMounts: |
| 65 | + - name: messages |
| 66 | + mountPath: /messages |
| 67 | + script: | |
| 68 | + #!/usr/bin/env ash |
| 69 | +
|
| 70 | + # Generate a private host key and give the Steps access to its public |
| 71 | + # key for their known_hosts file. |
| 72 | + ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key |
| 73 | + chmod 0600 /etc/ssh/ssh_host_rsa_key* |
| 74 | + HOST_PUBLIC_KEY=$(cat /etc/ssh/ssh_host_rsa_key.pub | awk '{ print $2 }') |
| 75 | + echo "localhost ssh-rsa $HOST_PUBLIC_KEY" > /messages/known_hosts |
| 76 | +
|
| 77 | + # Wait for a Step to supply the server a public key generated from creds-init |
| 78 | + # credentials. |
| 79 | + while [ ! -f /messages/authorized_keys ] ; do |
| 80 | + sleep 1 |
| 81 | + done |
| 82 | +
|
| 83 | + # Allow Steps to SSH login as root to this server. |
| 84 | + mkdir /root/.ssh |
| 85 | + cp /messages/authorized_keys /root/.ssh/ |
| 86 | +
|
| 87 | + # "Unlock" the root account, allowing SSH login to succeed. |
| 88 | + sed -i s/root:!/"root:*"/g /etc/shadow |
| 89 | +
|
| 90 | + # Create the git repo we're going to test against. |
| 91 | + cd /root/ |
| 92 | + mkdir repo |
| 93 | + cd repo |
| 94 | + git init . --bare |
| 95 | +
|
| 96 | + # Start the sshd server. |
| 97 | + /usr/sbin/sshd -E /var/log/sshd |
| 98 | + touch /messages/sshd-ready |
| 99 | + tail -f /var/log/sshd |
| 100 | + steps: |
| 101 | + - name: setup |
| 102 | + # This Step is only necessary as part of the test, it's not something you'll |
| 103 | + # ever need in a real-world scenario involving an external git repo. |
| 104 | + image: alpine/git:v2.24.3 |
| 105 | + securityContext: |
| 106 | + runAsUser: 0 |
| 107 | + volumeMounts: |
| 108 | + - name: messages |
| 109 | + mountPath: /messages |
| 110 | + script: | |
| 111 | + #!/usr/bin/env ash |
| 112 | +
|
| 113 | + # Generate authorized_keys file from the creds-init private key and give |
| 114 | + # it to the sidecar server so that Steps can successfully SSH login |
| 115 | + # using creds-init credentials. |
| 116 | + ssh-keygen -y -f $(credentials.path)/.ssh/id_ssh-key-for-git > /messages/authorized_keys |
| 117 | +
|
| 118 | + # Wait for sshd to start on the git server. |
| 119 | + while [ ! -f /messages/sshd-ready ] ; do |
| 120 | + sleep 1 |
| 121 | + done |
| 122 | + - name: git-clone-and-push |
| 123 | + image: alpine/git:v2.24.3 |
| 124 | + securityContext: |
| 125 | + runAsUser: 0 |
| 126 | + workingDir: /root |
| 127 | + volumeMounts: |
| 128 | + - name: messages |
| 129 | + mountPath: /messages |
| 130 | + script: | |
| 131 | + #!/usr/bin/env ash |
| 132 | + set -xe |
| 133 | +
|
| 134 | + if [ -d /tekton/home/.ssh ] ; then |
| 135 | + # When disable-home-env-overwrite is "false", creds-init credentials |
| 136 | + # will be copied to /tekton/home/.ssh by the entrypoint. But we need |
| 137 | + # them in /root/.ssh. |
| 138 | +
|
| 139 | + # Overwrite the creds-init known_hosts file with that of our test |
| 140 | + # git server. You wouldn't need to do this in any kind of real-world |
| 141 | + # scenario involving an external git repo. |
| 142 | + cp /messages/known_hosts $(credentials.path)/.ssh/ |
| 143 | +
|
| 144 | + # Symlink /tekton/creds/.ssh to /root/.ssh because this script issues |
| 145 | + # vanilla git commands of its own. Git PipelineResources and the git-clone |
| 146 | + # catalog task handle this for you. |
| 147 | + ln -s $(credentials.path)/.ssh /root/.ssh |
| 148 | + else |
| 149 | + # When disable-home-env-overwrite is "true", creds-init credentials |
| 150 | + # will be copied to /root/.ssh by the entrypoint. We just need to |
| 151 | + # overwrite the known_hosts file with that of our test git server. |
| 152 | + cp /messages/known_hosts /root/.ssh/known_hosts |
| 153 | + fi |
| 154 | +
|
| 155 | + git clone root@localhost:/root/repo ./repo |
| 156 | + cd repo |
| 157 | + git config user.email "[email protected]" |
| 158 | + git config user.name "Example" |
| 159 | + echo "Hello, world!" > README |
| 160 | + git add README |
| 161 | + git commit -m "Test commit!" |
| 162 | + git push origin master |
| 163 | + - name: git-clone-and-check |
| 164 | + image: gcr.io/tekton-releases/dogfooding/alpine-git-nonroot:mario |
| 165 | + # Because this Step runs with a non-root security context, the creds-init |
| 166 | + # credentials will fail to copy into /tekton/home. This happens because |
| 167 | + # our previous step _already_ wrote to /tekton/home and ran as a root |
| 168 | + # user. So there will be warning messages reporting "unsuccessful cred |
| 169 | + # copy". These can be safely ignored and instead this Step will copy |
| 170 | + # the credentials out of /tekton/creds to nonroot's HOME directory. |
| 171 | + securityContext: |
| 172 | + runAsUser: 1000 |
| 173 | + workingDir: /home/nonroot |
| 174 | + volumeMounts: |
| 175 | + - name: messages |
| 176 | + mountPath: /messages |
| 177 | + script: | |
| 178 | + #!/usr/bin/env ash |
| 179 | + set -xe |
| 180 | +
|
| 181 | + if [ -d /tekton/home/.ssh ] ; then |
| 182 | + # When disable-home-env-overwrite is "false", creds-init credentials |
| 183 | + # will be copied to /tekton/home/.ssh by the entrypoint. But we need |
| 184 | + # them in /home/nonroot/.ssh. |
| 185 | +
|
| 186 | + # Overwrite the creds-init known_hosts file with that of our test |
| 187 | + # git server. You wouldn't need to do this in any kind of real-world |
| 188 | + # scenario involving an external git repo. |
| 189 | + cp /messages/known_hosts $(credentials.path)/.ssh/ |
| 190 | +
|
| 191 | + # Symlink /tekton/creds/.ssh to /home/nonroot/.ssh because this script issues |
| 192 | + # vanilla git commands of its own and we're running as a non-root user. |
| 193 | + # Git PipelineResources and the git-clone catalog task handle this for you. |
| 194 | + ln -s $(credentials.path)/.ssh /home/nonroot/.ssh |
| 195 | + else |
| 196 | + # When disable-home-env-overwrite is "true", creds-init credentials |
| 197 | + # will be copied to /home/nonroot/.ssh by the entrypoint. We just need to |
| 198 | + # overwrite the known_hosts file with that of our test git server. |
| 199 | + cp /messages/known_hosts /home/nonroot/ssh/known_hosts |
| 200 | + fi |
| 201 | +
|
| 202 | + git clone root@localhost:/root/repo ./repo |
| 203 | + cd repo |
| 204 | + cat README | grep "Hello, world!" |
0 commit comments